mmplugins/imagingplugins/codecs/WMFCodec/WMFCodec.cpp
changeset 0 40261b775718
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/imagingplugins/codecs/WMFCodec/WMFCodec.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,2377 @@
+// Copyright (c) 1999-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:
+//
+
+#include <fbs.h>
+#include <hal.h>
+#include "WMFCodec.h"
+
+/*
+Not supported:
+0) Misc
+	// 0x0105 - SETRELABS
+	// 0x0231 - SETMAPPERFLAGS
+	// 0x0419 - FLOODFILL
+	// 0x0548 - EXTFLOODFILL
+	// 0x0626 - ESCAPE
+	// 0x0830 - CHORD
+1) Blitting
+	// 0x0107 - SETSTRETCHBLTMODE
+	// 0x0922 - BITBLT
+	// 0x0940 - DIBBITBLT
+	// 0x0b23 - STRETCHBLT
+	// 0x0d33 - SETDIBTODEV
+2) Clipping
+	// 0x0220 - OFFSETCLIPRGN
+	// 0x0415 - EXCLUDECLIPRECT
+3) Palettes
+	// 0x0035 - REALIZEPALETTE
+	// 0x0037 - SETPALENTRIES
+	// 0x00f7 - CREATEPALETTE
+	// 0x0139 - RESIZEPALETTE
+	// 0x0234 - SELECTPALETTE
+	// 0x0436 - ANIMATEPALETTE
+*/
+
+const TInt KFontNormalWeightLimit = 550;	// Halfway between FW_NORMAL and FW_BOLD
+const TInt KFontFixedPitch = 1;				// FIXED_PITCH
+const TInt KFontFamilyRoman = 1;			// FF_ROMAN
+const TInt KFontFamilySwiss = 2;			// FF_SWISS
+const TInt KFontFamilyMono = 3;				// FF_MODERN
+const TInt KFontFamilyScript = 4;			// FF_SCRIPT
+const TInt KFontFamilyDecorative = 5;		// FF_DECORATIVE
+
+const TInt KExtTextOutFlagClipped = 4;		// ETO_CLIPPED
+
+//const TInt KTextAlignFlagNoUpdateCP = 0;	// EABI warning removal
+//const TInt KTextAlignFlagUpdateCP = 1; // Not supported		// EABI warning removal
+//const TInt KTextAlignFlagLeft = 0;		// EABI warning removal
+const TInt KTextAlignFlagRight = 2;
+const TInt KTextAlignFlagCenter = 6;
+//const TInt KTextAlignFlagTop = 0;			// EABI warning removal
+const TInt KTextAlignFlagBottom = 8;
+const TInt KTextAlignFlagBaseline = 24;
+
+const TInt KTextAlignMaskHorz = 6;
+const TInt KTextAlignMaskVert = 24;
+
+const TUint KMaxProcessTime = 175000; //limit DoProcessL() to 175ms for liveliness
+
+// Wrapper class for drawing to the bitmap.
+// All drawing operations go through this class.
+CFbsBitGcWrapper* CFbsBitGcWrapper::NewL(CFbsDevice& aDevice, CFbsBitGcWrapper* aGc)
+	{
+	CFbsBitGcWrapper* self = new(ELeave) CFbsBitGcWrapper;
+
+	CleanupStack::PushL(self);
+	self->ConstructL(aDevice, aGc);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CFbsBitGcWrapper::CFbsBitGcWrapper():
+	iBrushColor(KRgbWhite),
+	iBrushStyle(CGraphicsContext::ENullBrush),
+	iPenColor(KRgbBlack),
+	iPenStyle(CGraphicsContext::ESolidPen),
+	iPenSize(1,1),
+	iTextColor(KRgbBlack),
+	iBackgroundColor(KRgbWhite)
+	{}
+
+void CFbsBitGcWrapper::ConstructL(CFbsDevice& aDevice, CFbsBitGcWrapper* aGc)
+	{
+	User::LeaveIfError(aDevice.CreateContext(iGc));
+	User::LeaveIfError(aDevice.CreateContext(iPolygonGc));
+	if (aGc)
+		{
+		iGc->CopySettings(*(aGc->iGc));
+		iGc->CancelClippingRegion();
+
+		iPolygonGc->CopySettings(*(aGc->iGc));
+		iPolygonGc->CancelClippingRegion();
+
+		iBrushColor = aGc->iBrushColor;
+		iBrushStyle = aGc->iBrushStyle;
+		iPenColor = aGc->iPenColor;
+		iPenStyle = aGc->iPenStyle;
+		iPenSize = aGc->iPenSize;
+
+		iTextColor = aGc->iTextColor;
+		iBackgroundColor = aGc->iBackgroundColor;
+		iPatternBrush = aGc->iPatternBrush;
+		}
+	}
+
+CFbsBitGcWrapper::~CFbsBitGcWrapper()
+	{
+	delete iGc;
+	delete iPolygonGc;
+	}
+
+void CFbsBitGcWrapper::SetPen(const CPen& aPen)
+	{
+	iPenStyle = aPen.iStyle;
+	iPenSize = aPen.iSize;
+	iPenColor = aPen.iColor;
+
+	iGc->SetPenStyle(iPenStyle);
+	iGc->SetPenSize(iPenSize);
+	iGc->SetPenColor(iPenColor);
+	}
+
+void CFbsBitGcWrapper::SetBrush(CBrush& aBrush)
+	{
+	iBrushColor = aBrush.iColor;
+	iBrushStyle = aBrush.iStyle;
+	iPatternBrush = (iBrushStyle == CGraphicsContext::EPatternedBrush) ? static_cast<CPatternBrush*> (&aBrush) : NULL;
+
+	iGc->SetBrushStyle(iBrushStyle);
+	iGc->SetBrushColor(iBrushColor);
+	}
+
+void CFbsBitGcWrapper::RestorePenAndBrush()
+	{
+	iGc->SetPenStyle(iPenStyle);
+	iGc->SetPenSize(iPenSize);
+	iGc->SetPenColor(iPenColor);
+
+	iGc->SetBrushStyle(iBrushStyle);
+	iGc->SetBrushColor(iBrushColor);
+	}
+
+void CFbsBitGcWrapper::DrawPolygonL(const TPoint* aPointList,TInt aNumPoints,CGraphicsContext::TFillRule aFillRule)
+	{
+	RealizeBrush();
+	if (iPenStyle == CGraphicsContext::ENullPen || iPenSize.iWidth == 0)
+		{
+		if (iBrushStyle != CGraphicsContext::ENullBrush)
+			{
+			iPolygonGc->CopySettings(*iGc);
+			iPolygonGc->CancelClippingRegion();
+
+			iPolygonGc->SetPenStyle(CGraphicsContext::ESolidPen);
+			iPolygonGc->SetPenSize(TSize(1,1));
+			iPolygonGc->SetPenColor(iBrushColor);
+
+			User::LeaveIfError(iPolygonGc->DrawPolygon(aPointList,aNumPoints,aFillRule));
+			}
+		}
+	else
+		User::LeaveIfError(iGc->DrawPolygon(aPointList,aNumPoints,aFillRule));
+	}
+
+const CFbsFont* CFbsBitGcWrapper::CurrentFont()
+	{
+	return iCurrentFont;
+	}
+
+void CFbsBitGcWrapper::Clear()
+	{
+	iGc->Clear();
+	}
+
+void CFbsBitGcWrapper::SetUnderlineStyle(TFontUnderline aUnderlineStyle)
+	{
+	iGc->SetUnderlineStyle(aUnderlineStyle);
+	}
+
+void CFbsBitGcWrapper::SetStrikethroughStyle(TFontStrikethrough aStrikethroughStyle)
+	{
+	iGc->SetStrikethroughStyle(aStrikethroughStyle);
+	}
+
+void CFbsBitGcWrapper::UseFont(const CFbsFont* aFont)
+	{
+	iGc->UseFont(aFont);
+	iCurrentFont = aFont;
+	}
+
+void CFbsBitGcWrapper::SetClippingRegion(const TRegion* aRegion)
+	{
+	iGc->SetClippingRegion(aRegion);
+	}
+
+void CFbsBitGcWrapper::SetCharJustification(TInt aExcessWidth, TInt aNumGaps)
+	{
+	iGc->SetCharJustification(aExcessWidth, aNumGaps);
+	}
+
+void CFbsBitGcWrapper::SetWordJustification(TInt aExcessWidth, TInt aNumChars)
+	{
+	iGc->SetWordJustification(aExcessWidth, aNumChars);
+	}
+
+void CFbsBitGcWrapper::DrawLineTo(const TPoint& aPoint)
+	{
+	iGc->DrawLineTo(aPoint);
+	}
+
+void CFbsBitGcWrapper::MoveTo(const TPoint& aPoint)
+	{
+	iGc->MoveTo(aPoint);
+	}
+
+void CFbsBitGcWrapper::DrawPolyLine(const TPoint* aPointList, TInt aNumPoints)
+	{
+	iGc->DrawPolyLine(aPointList, aNumPoints);
+	}
+
+void CFbsBitGcWrapper::DrawEllipse(const TRect& aRect)
+	{
+	RealizeBrush();
+	iGc->DrawEllipse(aRect);
+	}
+
+void CFbsBitGcWrapper::DrawRect(const TRect& aRect)
+	{
+	RealizeBrush();
+	iGc->DrawRect(aRect);
+	}
+
+void CFbsBitGcWrapper::DrawRoundRect(const TRect& aRect, const TSize& aEllipse)
+	{
+	RealizeBrush();
+	iGc->DrawRoundRect(aRect, aEllipse);
+	}
+
+void CFbsBitGcWrapper::SetPenStyle(CGraphicsContext::TPenStyle aPenStyle)
+	{
+	iGc->SetPenStyle(aPenStyle);
+	}
+
+void CFbsBitGcWrapper::SetBrushStyle(CGraphicsContext::TBrushStyle aBrushStyle)
+	{
+	iGc->SetBrushStyle(aBrushStyle);
+	}
+
+void CFbsBitGcWrapper::SetBrushColor(const TRgb& aColor)
+	{
+	iGc->SetBrushColor(aColor);
+	}
+
+void CFbsBitGcWrapper::SetDrawMode(CGraphicsContext::TDrawMode aDrawMode)
+	{
+	iGc->SetDrawMode(aDrawMode);
+	}
+
+void CFbsBitGcWrapper::SetPenColor(const TRgb& aColor)
+	{
+	iGc->SetPenColor(aColor);
+	}
+
+void CFbsBitGcWrapper::SetTextPenColor()
+	{
+	iGc->SetPenColor(iTextColor);
+	}
+
+void CFbsBitGcWrapper::Plot(const TPoint& aPoint)
+	{
+	iGc->Plot(aPoint);
+	}
+
+void CFbsBitGcWrapper::SetPenSize(const TSize& aSize)
+	{
+	iGc->SetPenSize(aSize);
+	}
+
+
+void CFbsBitGcWrapper::DrawArc(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd)
+	{
+	iGc->DrawArc(aRect, aStart, aEnd);
+	}
+
+void CFbsBitGcWrapper::DrawPie(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd)
+	{
+	RealizeBrush();
+	iGc->DrawPie(aRect, aStart, aEnd);
+	}
+
+void CFbsBitGcWrapper::DrawBitmap(const TRect& aDestRect, const CFbsBitmap* aSource, const TRect& aSourceRect)
+	{
+	iGc->DrawBitmap(aDestRect, aSource, aSourceRect);
+	}
+
+void CFbsBitGcWrapper::DrawText(const TDesC& aText,const TPoint& aPosition)
+	{
+	iGc->DrawText(aText, aPosition);
+	}
+
+void CFbsBitGcWrapper::UseBrushPattern(const CFbsBitmap* aPatternBitmap)
+	{
+	iGc->UseBrushPattern(aPatternBitmap);
+	}
+
+void CFbsBitGcWrapper::SetBackgroundColor(TRgb aBackgroundColor)
+	{
+	iBackgroundColor = aBackgroundColor;
+	}
+
+void CFbsBitGcWrapper::SetTextColor(TRgb aTextColor)
+	{
+	iTextColor = aTextColor;
+	}
+
+void CFbsBitGcWrapper::RealizeBrush()
+	{
+	if (iPatternBrush)
+		iPatternBrush->RealizeBrush(iTextColor, iBackgroundColor);
+	}
+
+// Wrapper class for drawing to the bitmap and mask.
+// All drawing operations are performed through this class when mask generation is requested.
+CFbsBitGcMaskWrapper* CFbsBitGcMaskWrapper::NewL(CFbsDevice& aDevice, CFbsDevice& aMaskDevice, CFbsBitGcMaskWrapper* aGc)
+	{
+	CFbsBitGcMaskWrapper* self = new(ELeave) CFbsBitGcMaskWrapper;
+
+	CleanupStack::PushL(self);
+	self->ConstructL(aDevice, aMaskDevice, aGc);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CFbsBitGcMaskWrapper::CFbsBitGcMaskWrapper()
+	{
+	}
+
+void CFbsBitGcMaskWrapper::ConstructL(CFbsDevice& aDevice, CFbsDevice& aMaskDevice, CFbsBitGcMaskWrapper* aGc)
+	{
+	CFbsBitGcWrapper::ConstructL(aDevice, aGc);
+	User::LeaveIfError(aMaskDevice.CreateContext(iMaskGc));
+	User::LeaveIfError(aMaskDevice.CreateContext(iPolygonMaskGc));
+	if (aGc)
+		{
+		iMaskGc->CopySettings(*(aGc->iMaskGc));
+		iMaskGc->CancelClippingRegion();
+
+		iPolygonMaskGc->CopySettings(*(aGc->iMaskGc));
+		iPolygonMaskGc->CancelClippingRegion();
+		}
+
+	// Set the pen color to white.
+	// (Ensures that all drawing operations will set pixels on the mask)
+	iMaskGc->SetPenColor(KRgbWhite);
+	iPolygonMaskGc->SetPenColor(KRgbWhite);
+	}
+
+CFbsBitGcMaskWrapper::~CFbsBitGcMaskWrapper()
+	{
+	delete iMaskGc;
+	delete iPolygonMaskGc;
+	}
+
+void CFbsBitGcMaskWrapper::SetPen(const CPen& aPen)
+	{
+	CFbsBitGcWrapper::SetPen(aPen);
+
+	iMaskGc->SetPenStyle(iPenStyle);
+	iMaskGc->SetPenSize(iPenSize);
+	}
+
+void CFbsBitGcMaskWrapper::SetBrush(CBrush& aBrush)
+	{
+	CFbsBitGcWrapper::SetBrush(aBrush);
+
+	if (!iPatternBrush)
+		iMaskGc->SetBrushStyle(iBrushStyle);
+	else
+		iMaskGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+	}
+
+void CFbsBitGcMaskWrapper::DrawPolygonL(const TPoint* aPointList,TInt aNumPoints,CGraphicsContext::TFillRule aFillRule)
+	{
+	CFbsBitGcWrapper::DrawPolygonL(aPointList, aNumPoints, aFillRule);
+	if (iPenStyle == CGraphicsContext::ENullPen || iPenSize.iWidth == 0)
+		{
+		if (iBrushStyle != CGraphicsContext::ENullBrush)
+			{
+			iPolygonMaskGc->CopySettings(*iMaskGc);
+			iPolygonMaskGc->CancelClippingRegion();
+
+			iPolygonMaskGc->SetPenStyle(CGraphicsContext::ESolidPen);
+			iPolygonMaskGc->SetPenSize(TSize(1,1));
+
+			User::LeaveIfError(iPolygonMaskGc->DrawPolygon(aPointList,aNumPoints,aFillRule));
+			}
+		}
+	else
+		User::LeaveIfError(iMaskGc->DrawPolygon(aPointList,aNumPoints,aFillRule));
+	}
+
+void CFbsBitGcMaskWrapper::Clear()
+	{
+	CFbsBitGcWrapper::Clear();
+
+	// Clear the mask to black.
+	iMaskGc->SetBrushColor(KRgbBlack);
+	iMaskGc->Clear();
+
+	// Reset the brush color to white.
+	iMaskGc->SetBrushColor(KRgbWhite);
+	}
+
+void CFbsBitGcMaskWrapper::SetUnderlineStyle(TFontUnderline aUnderlineStyle)
+	{
+	CFbsBitGcWrapper::SetUnderlineStyle(aUnderlineStyle);
+	iMaskGc->SetUnderlineStyle(aUnderlineStyle);
+	}
+
+void CFbsBitGcMaskWrapper::SetStrikethroughStyle(TFontStrikethrough aStrikethroughStyle)
+	{
+	CFbsBitGcWrapper::SetStrikethroughStyle(aStrikethroughStyle);
+	iMaskGc->SetStrikethroughStyle(aStrikethroughStyle);
+	}
+
+void CFbsBitGcMaskWrapper::UseFont(const CFbsFont* aFont)
+	{
+	CFbsBitGcWrapper::UseFont(aFont);
+	iMaskGc->UseFont(aFont);
+	}
+
+void CFbsBitGcMaskWrapper::SetClippingRegion(const TRegion* aRegion)
+	{
+	CFbsBitGcWrapper::SetClippingRegion(aRegion);
+	iMaskGc->SetClippingRegion(aRegion);
+	}
+
+void CFbsBitGcMaskWrapper::SetCharJustification(TInt aExcessWidth, TInt aNumGaps)
+	{
+	CFbsBitGcWrapper::SetCharJustification(aExcessWidth, aNumGaps);
+	iMaskGc->SetCharJustification(aExcessWidth, aNumGaps);
+	}
+
+void CFbsBitGcMaskWrapper::SetWordJustification(TInt aExcessWidth, TInt aNumChars)
+	{
+	CFbsBitGcWrapper::SetWordJustification(aExcessWidth, aNumChars);
+	iMaskGc->SetWordJustification(aExcessWidth, aNumChars);
+	}
+
+void CFbsBitGcMaskWrapper::DrawLineTo(const TPoint& aPoint)
+	{
+	CFbsBitGcWrapper::DrawLineTo(aPoint);
+	iMaskGc->DrawLineTo(aPoint);
+	}
+
+void CFbsBitGcMaskWrapper::MoveTo(const TPoint& aPoint)
+	{
+	CFbsBitGcWrapper::MoveTo(aPoint);
+	iMaskGc->MoveTo(aPoint);
+	}
+
+void CFbsBitGcMaskWrapper::DrawPolyLine(const TPoint* aPointList, TInt aNumPoints)
+	{
+	CFbsBitGcWrapper::DrawPolyLine(aPointList, aNumPoints);
+	iMaskGc->DrawPolyLine(aPointList, aNumPoints);
+	}
+
+void CFbsBitGcMaskWrapper::DrawEllipse(const TRect& aRect)
+	{
+	CFbsBitGcWrapper::DrawEllipse(aRect);
+	iMaskGc->DrawEllipse(aRect);
+	}
+
+void CFbsBitGcMaskWrapper::DrawRect(const TRect& aRect)
+	{
+	CFbsBitGcWrapper::DrawRect(aRect);
+	iMaskGc->DrawRect(aRect);
+	}
+
+void CFbsBitGcMaskWrapper::DrawRoundRect(const TRect& aRect, const TSize& aEllipse)
+	{
+	CFbsBitGcWrapper::DrawRoundRect(aRect, aEllipse);
+	iMaskGc->DrawRoundRect(aRect, aEllipse);
+	}
+
+void CFbsBitGcMaskWrapper::SetPenStyle(CGraphicsContext::TPenStyle aPenStyle)
+	{
+	CFbsBitGcWrapper::SetPenStyle(aPenStyle);
+	iMaskGc->SetPenStyle(aPenStyle);
+	}
+
+void CFbsBitGcMaskWrapper::SetBrushStyle(CGraphicsContext::TBrushStyle aBrushStyle)
+	{
+	CFbsBitGcWrapper::SetBrushStyle(aBrushStyle);
+	iMaskGc->SetBrushStyle(aBrushStyle);
+	}
+
+void CFbsBitGcMaskWrapper::SetDrawMode(CGraphicsContext::TDrawMode aDrawMode)
+	{
+	CFbsBitGcWrapper::SetDrawMode(aDrawMode);
+	}
+
+void CFbsBitGcMaskWrapper::Plot(const TPoint& aPoint)
+	{
+	CFbsBitGcWrapper::Plot(aPoint);
+	iMaskGc->Plot(aPoint);
+	}
+
+void CFbsBitGcMaskWrapper::SetPenSize(const TSize& aSize)
+	{
+	CFbsBitGcWrapper::SetPenSize(aSize);
+	iMaskGc->SetPenSize(aSize);
+	}
+
+void CFbsBitGcMaskWrapper::DrawArc(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd)
+	{
+	CFbsBitGcWrapper::DrawArc(aRect, aStart, aEnd);
+	iMaskGc->DrawArc(aRect, aStart, aEnd);
+	}
+
+void CFbsBitGcMaskWrapper::DrawPie(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd)
+	{
+	CFbsBitGcWrapper::DrawPie(aRect, aStart, aEnd);
+	iMaskGc->DrawPie(aRect, aStart, aEnd);
+	}
+
+void CFbsBitGcMaskWrapper::DrawBitmap(const TRect& aDestRect, const CFbsBitmap* aSource, const TRect& aSourceRect)
+	{
+	CFbsBitGcWrapper::DrawBitmap(aDestRect, aSource, aSourceRect);
+	iMaskGc->Clear(aDestRect);
+	}
+
+void CFbsBitGcMaskWrapper::DrawText(const TDesC& aText,const TPoint& aPosition)
+	{
+	CFbsBitGcWrapper::DrawText(aText, aPosition);
+	iMaskGc->DrawText(aText, aPosition);
+	}
+
+
+void CPen::Apply(CFbsBitGcWrapper* aGc)
+	{
+	aGc->SetPen(*this);
+	}
+
+TInt CPen::Type() const
+	{
+	return KWmfGraphicsObjectPen;
+	}
+
+void CDummyBrush::Apply(CFbsBitGcWrapper* /* aGc */)
+	{
+	}
+
+TInt CDummyBrush::Type() const
+	{
+	return KWmfGraphicsObjectDummyBrush;
+	}
+
+void CBrush::Apply(CFbsBitGcWrapper* aGc)
+	{
+	aGc->SetBrush(*this);
+	}
+
+TInt CBrush::Type() const
+	{
+	return KWmfGraphicsObjectBrush;
+	}
+
+CPatternBrush* CPatternBrush::NewL()
+	{
+	CPatternBrush* self = new(ELeave) CPatternBrush;
+
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CPatternBrush::ConstructL()
+	{
+	iBitmap = new(ELeave) CFbsBitmap;
+	}
+
+CPatternBrush::CPatternBrush()
+: iTextColor(KRgbWhite), iBackgroundColor(KRgbWhite)
+	{
+	iStyle = CGraphicsContext::EPatternedBrush;
+	}
+
+CPatternBrush::~CPatternBrush()
+	{
+	delete iBitmap;
+	delete[] iBitmapBits;
+	}
+
+void CPatternBrush::Apply(CFbsBitGcWrapper* aGc)
+	{
+	aGc->UseBrushPattern(iBitmap);
+	CBrush::Apply(aGc);
+	}
+
+TInt CPatternBrush::Type() const
+	{
+	return KWmfGraphicsObjectPatternBrush;
+	}
+
+void CPatternBrush::SetBitmapBits(TUint8* aBitmapBits)
+	{
+	iBitmapBits = aBitmapBits;
+	}
+
+void CPatternBrush::RealizeBrush(TRgb aTextColor, TRgb aBackgroundColor)
+	{
+	if (!iBitmapBits)
+		return;
+
+	if ((aTextColor == iTextColor) && (aBackgroundColor == iBackgroundColor))
+		return;
+
+	iTextColor = aTextColor;
+	iBackgroundColor = aBackgroundColor;
+
+	TInt width = iBitmap->SizeInPixels().iWidth;
+	TInt height = iBitmap->SizeInPixels().iHeight;
+	TInt padding = ((width + 31) & ~31) - width;
+	TUint pixelMask = 0x80;
+	TUint8* bytePtr = iBitmapBits;
+	TBitmapUtil util(iBitmap);
+	for (TInt y = height - 1; y >= 0; y--)
+		{
+		util.Begin(TPoint(0,y));
+
+		TInt x;
+		for (x = 0; x < width; x++)
+			{
+			TRgb color((bytePtr[0] & pixelMask) ? iBackgroundColor : iTextColor);
+			util.SetPixel(color.Color64K());
+			util.IncXPos();
+
+			pixelMask >>= 1;
+			if (pixelMask == 0)
+				{
+				pixelMask = 0x80;
+				bytePtr++;
+				}
+			}
+
+		for (x = 0 ; x<padding ; x++)
+			{
+			pixelMask >>= 1;
+			if (pixelMask == 0)
+				{
+				pixelMask = 0x80;
+				bytePtr++;
+				}
+			}
+
+		util.End();
+		}
+	}
+
+CFbsBitmap* CPatternBrush::Bitmap()
+	{
+	return iBitmap;
+	}
+
+
+CFontObject::CFontObject(CFbsDevice& aDevice,CFbsFont& aFont,TBool aUnderline,TBool aStrikeOut):
+	iDevice(aDevice),
+	iFont(aFont),
+	iUnderline(aUnderline ? EUnderlineOn : EUnderlineOff),
+	iStrikeOut(aStrikeOut ? EStrikethroughOn : EStrikethroughOff)
+	{}
+
+CFontObject::~CFontObject()
+	{
+	iDevice.ReleaseFont(&iFont);
+	}
+
+void CFontObject::Apply(CFbsBitGcWrapper* aGc)
+	{
+	aGc->SetUnderlineStyle(iUnderline);
+	aGc->SetStrikethroughStyle(iStrikeOut);
+	aGc->UseFont(&iFont);
+	}
+
+TInt CFontObject::Type() const
+	{
+	return KWmfGraphicsObjectFont;
+	}
+
+
+CRectRegion::CRectRegion(CFbsDevice& aDevice, TRegion& aClipRegion, TInt aLeft, TInt aTop, TInt aRight, TInt aBottom):
+	iRect(aLeft, aTop, aRight, aBottom), iDevice(aDevice), iClipRegion(aClipRegion)
+	{}
+
+void CRectRegion::Apply(CFbsBitGcWrapper* aGc)
+	{
+	iClipRegion.Clear();
+	TRect bitmapRect(iDevice.SizeInPixels());
+	iClipRegion.AddRect(bitmapRect);
+
+	TRegionFix<1> rectRegion;
+	rectRegion.AddRect(iRect);
+
+	iClipRegion.Intersect(rectRegion);
+	aGc->SetClippingRegion(&iClipRegion);
+	}
+
+TInt CRectRegion::Type() const
+	{
+	return KWmfGraphicsObjectRegion;
+	}
+
+
+void CPaletteObject::Apply(CFbsBitGcWrapper* /* aGc */)
+	{
+	}
+
+TInt CPaletteObject::Type() const
+	{
+	return KWmfGraphicsObjectPalette;
+	}
+
+
+//
+// CWmfReadCodec
+//
+
+CWmfReadCodec::CWmfReadCodec(TInt aWordsExpected)
+	: iWordsExpected(aWordsExpected)
+	{
+	}
+
+CWmfReadCodec::~CWmfReadCodec()
+	{
+	delete[] iPointArray;
+	iSavedGcStack.ResetAndDestroy();
+
+	for (TInt index = 0; index < KWmfMaxGraphicsObjectCount; index++)
+		delete iGraphicsObject[index];
+
+	delete iDefaultPen;
+	delete iDefaultBrush;
+	delete iGc;
+	delete iDevice;
+	delete iMaskDevice;
+	delete[] iAccumulator;
+	}
+
+CWmfReadCodec* CWmfReadCodec::NewL(TInt aWordsExpected)
+	{
+	CWmfReadCodec* self = new(ELeave) CWmfReadCodec(aWordsExpected);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self); 
+	return self;
+	}
+
+void CWmfReadCodec::ConstructL()
+	{
+	CImageReadCodec::ConstructL();
+
+	iDefaultPen = new(ELeave) CPen;
+	iDefaultBrush = new(ELeave) CBrush;
+	}
+
+void CWmfReadCodec::InitFrameL(TFrameInfo& aFrameInfo, CFrameImageData& /*aFrameImageData*/, TBool /*aDisableErrorDiffusion*/, CFbsBitmap& aBitmap, CFbsBitmap* aDestinationMask)
+	{
+	iWordsProcessed = 0;
+
+	for (TInt index = 0; index < KWmfMaxGraphicsObjectCount; index++)
+		{
+		delete iGraphicsObject[index];
+		iGraphicsObject[index] = NULL;
+		}
+
+	delete iGc; iGc = NULL;
+	delete iDevice;	iDevice = NULL;
+	delete iMaskDevice; iMaskDevice = NULL;
+	iDevice = CFbsBitmapDevice::NewL(&aBitmap);
+
+	if ((aFrameInfo.iFlags & TFrameInfo::ETransparencyPossible) && aDestinationMask)
+		{
+		iMaskDevice = CFbsBitmapDevice::NewL(aDestinationMask);
+		iGc = CFbsBitGcMaskWrapper::NewL(*iDevice, *iMaskDevice);
+		}
+	else
+		{
+		iGc = CFbsBitGcWrapper::NewL(*iDevice);
+		}
+	
+	if ((aFrameInfo.iFlags & TFrameInfo::ETransparencyPossible) && !aDestinationMask && aBitmap.DisplayMode() == EColor16MA)
+		{
+		// Special case of single 16MA destination bitmap.
+		const TRgb transparentBlack(0x000000, 0x00);
+		ClearBitmapL(aBitmap, transparentBlack);
+		}
+	else
+		{
+		iGc->Clear(); // Ensure bitmap is cleared. (Also clear the mask if we are generating one)	
+		}
+	
+	iBkModeOpaque = EFalse;
+	iMapMode = EMapModeTEXT;
+	iWindowOrg.SetXY(0,0);
+	iWindowExt = aBitmap.SizeInPixels();
+	iViewportOrg.SetXY(0,0);
+	iViewportExt = iWindowExt;
+
+	iClipRegion.Clear();
+	TRect bitmapRect(iDevice->SizeInPixels());
+	iClipRegion.AddRect(bitmapRect);
+		
+	iFillRule = CGraphicsContext::EAlternate;
+
+	delete[] iAccumulator; iAccumulator = NULL;
+	iAccumulatorPtr = NULL;
+	iAccumulatorSizeInWords = 0;
+	iLookingForRecord = ETrue;
+	iRecordSizeInWords = 0;
+	iFunction = 0;
+	iWordsToRead = 0;
+	iFinished = EFalse;
+	}
+
+TFrameState CWmfReadCodec::ProcessFrameL(TBufPtr8& aSrc)
+	{
+	TUint16* startDataPtr = REINTERPRET_CAST(TUint16*,&aSrc[0]);
+	TUint16* dataPtr = startDataPtr;
+	TUint16* dataPtrLimit = dataPtr + Min(TInt(aSrc.Length() / sizeof(TUint16)),iWordsExpected - iWordsProcessed);
+
+	DoProcessL(dataPtr,dataPtrLimit);
+
+	TInt wordsUsed = dataPtr - startDataPtr;
+	aSrc.Shift(wordsUsed * sizeof(TUint16));
+	iWordsProcessed += wordsUsed;
+
+	if (iWordsProcessed >= iWordsExpected || iFinished)
+		return EFrameComplete;
+
+	return EFrameIncomplete;
+	}
+
+void CWmfReadCodec::DoProcessL(TUint16*& aDataPtr,const TUint16* aDataPtrLimit)
+	{
+	const TUint16* safeDataPtrLimit = aDataPtrLimit - KWmfMinRecordSizeInWords;
+	
+	//Do not spend more than KMaxProcessTime here
+	TInt systemTickPeriod;
+	User::LeaveIfError(HAL::Get(HAL::ESystemTickPeriod,systemTickPeriod));
+
+	TUint currentTick = User::TickCount();
+	const TUint tickLimit = currentTick + (KMaxProcessTime / systemTickPeriod);
+
+	//Disable tick check if tickLimit overflow
+	TBool disableTickCheck = EFalse;
+	if(tickLimit<=currentTick)
+		disableTickCheck = ETrue;
+
+	while (aDataPtr <= aDataPtrLimit && (disableTickCheck || currentTick < tickLimit))
+		{
+		if (iLookingForRecord) // Find record
+			{
+			if (aDataPtr > safeDataPtrLimit) // Ensures that a record header can always be safely read
+				return;
+
+			iRecordSizeInWords = (aDataPtr[1] << 16) | aDataPtr[0];
+			if (iRecordSizeInWords < KWmfMinRecordSizeInWords || iRecordSizeInWords > iWordsExpected)
+				User::Leave(KErrCorrupt);
+
+			iFunction = aDataPtr[2];
+
+			iWordsToRead = iRecordSizeInWords - KWmfMinRecordSizeInWords;
+			if (iWordsToRead > aDataPtrLimit - aDataPtr - KWmfMinRecordSizeInWords) // Check to see if we need to accumulate data
+				{
+				if (iWordsToRead > iAccumulatorSizeInWords)
+					{
+					delete[] iAccumulator;
+					iAccumulator = NULL;
+					iAccumulatorSizeInWords = 0;
+
+					iAccumulator = new(ELeave) TUint16[iWordsToRead];
+					iAccumulatorSizeInWords = iWordsToRead;
+					}
+
+				iAccumulatorPtr = iAccumulator;
+				}
+			else
+				iAccumulatorPtr = NULL;
+
+			aDataPtr += KWmfMinRecordSizeInWords;
+			iLookingForRecord = EFalse;
+			}
+		else if (iFunction == KWmfTerminateFunction) // Finished
+			{
+			iFinished = ETrue;
+			return;
+			}
+		else if (iAccumulatorPtr && iWordsToRead > 0) // Accumulate data
+			{
+			const TInt wordsToAccumulate = Min(iWordsToRead,aDataPtrLimit - aDataPtr);
+			Mem::Copy(iAccumulatorPtr,aDataPtr,wordsToAccumulate * sizeof(TUint16));
+			aDataPtr += wordsToAccumulate;
+			iAccumulatorPtr += wordsToAccumulate;
+			iWordsToRead -= wordsToAccumulate;
+
+			if (iWordsToRead > 0)
+				return;
+			}
+		else // Process data
+			{
+			TUint16* dataPtr = iAccumulatorPtr ? iAccumulator : aDataPtr;
+
+			if (iFunction < 0x0230)
+				{
+				if (iFunction < 0x0130)
+					DoProcess00L(iFunction,dataPtr);
+				else
+					DoProcess01L(iFunction,dataPtr);
+				}
+			else
+				{
+				if (iFunction < 0x500)
+					DoProcess10L(iFunction,dataPtr);
+				else
+					DoProcess11L(iFunction,dataPtr);
+				}
+
+			if (iAccumulatorPtr)
+				{
+				if (iAccumulatorSizeInWords > 0x800)
+					{
+					delete[] iAccumulator;
+					iAccumulator = NULL;
+					iAccumulatorSizeInWords = 0;
+					}
+
+				iAccumulatorPtr = NULL;
+				}
+			else
+				aDataPtr += iWordsToRead;
+
+			iLookingForRecord = ETrue;
+			}
+		currentTick = User::TickCount();
+		}
+	}
+
+void CWmfReadCodec::DoProcess00L(TInt aFunction,TUint16* aArgPtr)
+	{
+	if (aFunction < 0x0107)
+		{
+		if (aFunction < 0x0103)
+			DoProcess0000L(aFunction,aArgPtr);
+		else
+			DoProcess0001L(aFunction,aArgPtr);
+		}
+	else
+		{
+		if (aFunction < 0x012b)
+			DoProcess0010L(aFunction,aArgPtr);
+		else
+			DoProcess0011L(aFunction,aArgPtr);
+		}
+	}
+
+void CWmfReadCodec::DoProcess01L(TInt aFunction,TUint16* aArgPtr)
+	{
+	if (aFunction < 0x020d)
+		{
+		if (aFunction < 0x0205)
+			DoProcess0100L(aFunction,aArgPtr);
+		else
+			DoProcess0101L(aFunction,aArgPtr);
+		}
+	else
+		{
+		if (aFunction < 0x0212)
+			DoProcess0110L(aFunction,aArgPtr);
+		else
+			DoProcess0111L(aFunction,aArgPtr);
+		}
+	}
+
+void CWmfReadCodec::DoProcess10L(TInt aFunction,TUint16* aArgPtr)
+	{
+	if (aFunction < 0x0413)
+		{
+		if (aFunction < 0x0300)
+			DoProcess1000L(aFunction,aArgPtr);
+		else
+			DoProcess1001L(aFunction,aArgPtr);
+		}
+	else
+		{
+		if (aFunction < 0x041a)
+			DoProcess1010L(aFunction,aArgPtr);
+		else
+			DoProcess1011L(aFunction,aArgPtr);
+		}
+	}
+
+void CWmfReadCodec::DoProcess11L(TInt aFunction,TUint16* aArgPtr)
+	{
+	if (aFunction < 0x0820)
+		{
+		if (aFunction < 0x0620)
+			DoProcess1100L(aFunction,aArgPtr);
+		else
+			DoProcess1101L(aFunction,aArgPtr);
+		}
+	else
+		{
+		if (aFunction < 0x0b00)
+			DoProcess1110L(aFunction,aArgPtr);
+		else
+			DoProcess1111L(aFunction,aArgPtr);
+		}
+	}
+
+void CWmfReadCodec::DoProcess0000L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0035 - REALIZEPALETTE
+	// 0x0037 - SETPALENTRIES
+	// 0x00f7 - CREATEPALETTE
+
+	switch (aFunction)
+		{
+	case 0x001e: // SAVEDC
+		{
+		CFbsBitGcWrapper* gcCopy = CloneGcL();
+		CleanupStack::PushL(gcCopy);
+
+		User::LeaveIfError(iSavedGcStack.Append(gcCopy));
+		CleanupStack::Pop(); // gcCopy
+		}
+		break;
+	case 0x00f7: // CREATEPALETTE
+		AddGraphicsObject(new(ELeave) CPaletteObject);
+		// Create the object to maintain the handle list
+		break;
+	case 0x0102: // SETBKMODE
+		// 1 = TRANSPARENT, 2 = OPAQUE
+		iBkModeOpaque = (aArgPtr[0] == 2);
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess0001L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0105 - SETRELABS
+
+	switch (aFunction)
+		{
+	case 0x0103: // SETMAPMODE
+		iMapMode = TMapMode(aArgPtr[0]);
+		break;
+	case 0x0104: // SETROP2
+		SetROP(iGc,aArgPtr[0]);
+		break;
+	case 0x0106: // SETPOLYFILLMODE
+		// 1 = ALTERNATE, 2 = WINDING
+		iFillRule = (aArgPtr[0] == 2) ? CGraphicsContext::EWinding : CGraphicsContext::EAlternate;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess0010L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0107 - SETSTRETCHBLTMODE
+
+	switch (aFunction)
+		{
+	case 0x0108: // SETTEXTCHAREXTRA
+		{
+		const TInt extraSpace = LogicalSizeToDeviceSize(aArgPtr[0],ETrue);
+		if (extraSpace != 0)
+			{
+			const TInt numChars = KMaxTInt / extraSpace; // Choose a suitably high number of chars to keep the char spacing going
+			iGc->SetCharJustification(extraSpace * numChars,numChars);
+			}
+		}
+		break;
+	case 0x0127: // RESTOREDC
+		{
+		const TInt savedGcCount = iSavedGcStack.Count();
+		if (savedGcCount > 0)
+			{
+			delete iGc;
+			iGc = iSavedGcStack[savedGcCount - 1];
+			iSavedGcStack.Remove(savedGcCount - 1);
+			ASSERT(iGc);
+			}
+		}
+		break;
+	case 0x012a: // INVERTREGION
+		{
+		CGraphicsObject* object = GraphicsObject(aArgPtr[0]);
+		if (object && object->Type() == KWmfGraphicsObjectRegion)
+			{
+			CRectRegion* rectRgn = STATIC_CAST(CRectRegion*,object);
+			CFbsBitGcWrapper* gc = CloneGcL();
+
+			gc->SetPenStyle(CGraphicsContext::ENullPen);
+			gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+			gc->SetBrushColor(KRgbWhite);
+			gc->SetDrawMode(CGraphicsContext::EDrawModeXOR);
+			gc->DrawRect(rectRgn->iRect);
+
+			delete gc;
+			}
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess0011L(TInt aFunction,TUint16* aArgPtr)
+	{
+	switch (aFunction)
+		{
+	case 0x012e: // SETTEXTALIGN
+		iTextAlignFlags = aArgPtr[0];
+		break;
+	case 0x012b: // PAINTREGION
+		{
+		CGraphicsObject* object = GraphicsObject(aArgPtr[0]);
+		if (object && object->Type() == KWmfGraphicsObjectRegion)
+			{
+			CRectRegion* rectRgn = STATIC_CAST(CRectRegion*,object);
+			CFbsBitGcWrapper* gc = CloneGcL();
+
+			gc->SetPenStyle(CGraphicsContext::ENullPen);
+			gc->DrawRect(rectRgn->iRect);
+
+			delete gc;
+			}
+		}
+		break;
+	case 0x012c: // SELECTCLIPREGION
+	case 0x012d: // SELECTOBJECT
+		{
+		CGraphicsObject* object = GraphicsObject(aArgPtr[0]);
+		if (object)
+			object->Apply(iGc);
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess0100L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0139 - RESIZEPALETTE
+
+	switch (aFunction)
+		{
+	case 0x01f9: // CREATEPATTERNBRUSH
+	case 0x0142: // DIBCREATEPATTERNBRUSH
+		{
+		CPatternBrush* patternBrush = CPatternBrush::NewL();
+
+		TInt err = ExtractDib(aArgPtr + 2, patternBrush);
+		if (err == KErrNone)
+			AddGraphicsObject(patternBrush);
+		else
+			{
+			// Coverity reports a leave_without_push error here because
+			// CPatternBrush has a CFbsBitmap member which can panic
+			// during its destructor. The panic has a trapped leave and
+			// for some reason coverity does not recognise it.
+			// Mark as false positive
+			// coverity[leave_without_push : FALSE]
+			delete patternBrush;
+
+			if (err == KErrNotSupported) // Ignore KErrNotSupported
+				AddGraphicsObject(new(ELeave) CDummyBrush); // Create the object to maintain the handle list
+			else
+				User::Leave(err);
+			}
+		}
+		break;
+	case 0x01f0: // DELETEOBJECT
+		RemoveGraphicsObject(aArgPtr[0]);
+		break;
+	case 0x0201: // SETBKCOLOR
+		iGc->SetBackgroundColor(ExtractColor(aArgPtr));
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess0101L(TInt aFunction,TUint16* aArgPtr)
+	{
+	switch (aFunction)
+		{
+	case 0x0209: // SETTEXTCOLOR
+		iGc->SetTextColor(ExtractColor(aArgPtr));
+		break;
+	case 0x020a: // SETTEXTJUSTIFICATION
+		iGc->SetWordJustification(LogicalSizeToDeviceSize(aArgPtr[1],ETrue),aArgPtr[0]);
+		break;
+	case 0x020b: // SETWINDOWORG
+		iWindowOrg.SetXY(REINTERPRET_CAST(TInt16*,aArgPtr)[1],REINTERPRET_CAST(TInt16*,aArgPtr)[0]);
+		break;
+	case 0x020c: // SETWINDOWEXT
+		iWindowExt.SetSize(REINTERPRET_CAST(TInt16*,aArgPtr)[1],REINTERPRET_CAST(TInt16*,aArgPtr)[0]);
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess0110L(TInt aFunction,TUint16* aArgPtr)
+	{
+	switch (aFunction)
+		{
+	case 0x020d: // SETVIEWPORTORG
+		if (iIgnoreViewportMetaData == EFalse)
+			iViewportOrg.SetXY(REINTERPRET_CAST(TInt16*,aArgPtr)[1],REINTERPRET_CAST(TInt16*,aArgPtr)[0]);
+		break;
+	case 0x020e: // SETVIEWPORTEXT
+		if (iIgnoreViewportMetaData == EFalse)
+			iViewportExt.SetSize(REINTERPRET_CAST(TInt16*,aArgPtr)[1],REINTERPRET_CAST(TInt16*,aArgPtr)[0]);
+		break;
+	case 0x020f: // OFFSETWINDOWORG
+		iWindowOrg += TPoint(REINTERPRET_CAST(TInt16*,aArgPtr)[1],REINTERPRET_CAST(TInt16*,aArgPtr)[0]);
+		break;
+	case 0x0211: // OFFSETVIEWPORTORG
+		if (iIgnoreViewportMetaData == EFalse)
+			iViewportOrg += TPoint(REINTERPRET_CAST(TInt16*,aArgPtr)[1],REINTERPRET_CAST(TInt16*,aArgPtr)[0]);
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess0111L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0220 - OFFSETCLIPRGN
+
+	switch (aFunction)
+		{
+	case 0x0213: // LINETO
+		iGc->DrawLineTo(ExtractPoint(aArgPtr,EFalse));
+		break;
+	case 0x0214: // MOVETO
+		iGc->MoveTo(ExtractPoint(aArgPtr,EFalse));
+		break;
+	case 0x0228: // FILLREGION
+		{
+		CGraphicsObject* regionObject = GraphicsObject(aArgPtr[0]);
+		CGraphicsObject* brushObject = GraphicsObject(aArgPtr[1]);
+		if (regionObject && (regionObject->Type() == KWmfGraphicsObjectRegion)
+			&& brushObject && ((brushObject->Type() == KWmfGraphicsObjectBrush) || (brushObject->Type() == KWmfGraphicsObjectPatternBrush)))
+			{
+			CRectRegion* rectRgn = STATIC_CAST(CRectRegion*,regionObject);
+			CFbsBitGcWrapper* gc = CloneGcL();
+
+			gc->SetPenStyle(CGraphicsContext::ENullPen);
+			brushObject->Apply(iGc);
+			gc->DrawRect(rectRgn->iRect);
+
+			delete gc;
+			}
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess1000L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0231 - SETMAPPERFLAGS
+	// 0x0234 - SELECTPALETTE
+
+	switch (aFunction)
+		{
+	case 0x02fa: // CREATEPENINDIRECT
+		{
+		TInt style = aArgPtr[0];
+
+		CPen* pen = NULL;
+
+		if (iDefaultPen)
+			{
+			pen = iDefaultPen;
+			iDefaultPen = NULL;
+			}
+		else
+			pen = new(ELeave) CPen;
+
+		switch (style)
+			{
+		case 0: // PS_SOLID
+			pen->iStyle = CGraphicsContext::ESolidPen;
+			break;
+		case 1: // PS_DASH
+			pen->iStyle = CGraphicsContext::EDashedPen;
+			break;
+		case 2: // PS_DOT
+			pen->iStyle = CGraphicsContext::EDottedPen;
+			break;
+		case 3: // PS_DASHDOT
+			pen->iStyle = CGraphicsContext::EDotDashPen;
+			break;
+		case 4: // PS_DASHDOTDOT
+			pen->iStyle = CGraphicsContext::EDotDotDashPen;
+			break;
+		case 5: // PS_NULL
+			pen->iStyle = CGraphicsContext::ENullPen;
+			break;
+		case 6: // PS_INSIDEFRAME
+		case 7: // PS_USERSTYLE
+		case 8: // PS_ALTERNATE
+		default:
+			pen->iStyle = CGraphicsContext::ESolidPen;
+			break;
+			}
+		pen->iSize.iWidth = Max(LogicalSizeToDeviceSize(aArgPtr[1],ETrue),1);
+		pen->iSize.iHeight = Max(LogicalSizeToDeviceSize(aArgPtr[1],EFalse),1);
+		pen->iColor = ExtractColor(aArgPtr + 3);
+
+		AddGraphicsObject(pen);
+		}
+		break;
+	case 0x02fb: // CREATEFONTINDIRECT
+		{
+		const TInt height = Abs(TInt((TInt16)aArgPtr[0]));
+		const TInt weight = Abs(TInt(aArgPtr[4]));
+		const TInt italic = Abs(aArgPtr[5] & 0xff);
+		const TInt underline = Abs(aArgPtr[5] >> 8);
+		const TInt strikeOut = Abs(aArgPtr[6] & 0xff);
+		const TInt pitchAndFamily = Abs(aArgPtr[8] >> 8);
+
+		TFontSpec fontSpec;
+		fontSpec.iTypeface.SetIsProportional(((pitchAndFamily & 3) != KFontFixedPitch));
+
+		switch (pitchAndFamily >> 4)
+			{
+		case KFontFamilyRoman:
+		case KFontFamilyScript:
+		case KFontFamilyDecorative:
+			fontSpec.iTypeface.SetIsProportional(ETrue);
+			fontSpec.iTypeface.SetIsSerif(ETrue);
+			break;
+		case KFontFamilySwiss:
+			fontSpec.iTypeface.SetIsProportional(ETrue);
+			fontSpec.iTypeface.SetIsSerif(EFalse);
+			break;
+		case KFontFamilyMono:
+			fontSpec.iTypeface.SetIsProportional(EFalse);
+			fontSpec.iTypeface.SetIsSerif(ETrue);
+			break;
+		default:
+			break;
+			}
+
+		const TInt fontHeight = LogicalSizeToDeviceSize(height,EFalse);
+		fontSpec.iHeight = Max(fontHeight,1);
+
+		if (weight > KFontNormalWeightLimit)
+			fontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+		if (italic)
+			fontSpec.iFontStyle.SetPosture(EPostureItalic);
+
+		CFbsFont* font = NULL;
+		User::LeaveIfError(iDevice->GetNearestFontInPixels(font,fontSpec));
+
+		CFontObject* fontObject = new CFontObject(*iDevice,*font,underline,strikeOut);
+
+		if (!fontObject)
+			{
+			iDevice->ReleaseFont(font);
+			User::Leave(KErrNoMemory);
+			}
+		else
+			AddGraphicsObject(fontObject);
+		}
+		break;
+	case 0x02fc: // CREATEBRUSHINDIRECT
+		{
+		TInt style = aArgPtr[0];
+		TInt hatch = aArgPtr[3];
+
+		CBrush* brush = NULL;
+
+		if (iDefaultBrush)
+			{
+			brush = iDefaultBrush;
+			iDefaultBrush = NULL;
+			}
+		else
+			brush = new(ELeave) CBrush;
+
+		switch (style)
+			{
+		case 0: // BS_SOLID
+			brush->iStyle = CGraphicsContext::ESolidBrush;
+			break;
+		case 1: // BS_NULL, BS_HOLLOW           
+			brush->iStyle = CGraphicsContext::ENullBrush;
+			break;
+		case 2: // BS_HATCHED
+			switch (hatch)
+				{
+			case 0: // HS_HORIZONTAL
+				brush->iStyle = CGraphicsContext::EHorizontalHatchBrush;
+				break;
+			case 1: // HS_VERTICAL
+				brush->iStyle = CGraphicsContext::EVerticalHatchBrush;
+				break;
+			case 2: // HS_FDIAGONAL
+				brush->iStyle = CGraphicsContext::EForwardDiagonalHatchBrush;
+				break;
+			case 3: // HS_BDIAGONAL
+				brush->iStyle = CGraphicsContext::ERearwardDiagonalHatchBrush;
+				break;
+			case 4: // HS_CROSS
+				brush->iStyle = CGraphicsContext::ESquareCrossHatchBrush;
+				break;
+			case 5: // HS_DIAGCROSS
+				brush->iStyle = CGraphicsContext::EDiamondCrossHatchBrush;
+				break;
+			default:
+				brush->iStyle = CGraphicsContext::ESolidBrush;
+				break;
+				}
+			break;
+		case 3: // BS_PATTERN
+		case 4: // BS_INDEXED
+		case 5: // BS_DIBPATTERN
+		case 6: // BS_DIBPATTERNPT
+		case 7: // BS_PATTERN8X8
+		case 8: // BS_DIBPATTERN8X8
+		case 9: // BS_MONOPATTERN
+		default:
+			brush->iStyle = CGraphicsContext::ESolidBrush;
+			break;
+			}
+		brush->iColor = ExtractColor(aArgPtr + 1);
+
+		AddGraphicsObject(brush);
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess1001L(TInt aFunction,TUint16* aArgPtr)
+	{
+	switch (aFunction)
+		{
+	case 0x0324: // POLYGON
+	case 0x0325: // POLYLINE
+		{
+		//check if the record size sufficient for polygon/polyline record.
+		if(iRecordSizeInWords < KWmfPolyRecordSizeInWords)
+			{
+			User::Leave(KErrCorrupt);
+			}
+
+		const TInt numPoints = aArgPtr[0];
+		if (numPoints <= 0)
+			break;
+
+		//check if the entire data about polygon/polyline is within the record.Each point needs 2 words
+		if(iRecordSizeInWords < (KWmfPolyRecordSizeInWords  + (numPoints * 2)))
+			{
+			User::Leave(KErrCorrupt);
+			}
+
+		if (numPoints > iPointArrayEntries)
+			{
+			delete[] iPointArray;
+			iPointArray = NULL;
+			iPointArray = new(ELeave) TPoint[numPoints];
+			iPointArrayEntries = numPoints;
+			}
+
+		TUint16* pointPtr = aArgPtr + 1;
+		TPoint* pointArrayPtr = iPointArray;
+
+		for (TInt count = 0; count < numPoints; count++)
+			{
+			*pointArrayPtr++ = ExtractPoint(pointPtr,ETrue);
+			pointPtr += 2;
+			}
+
+		if (aFunction == 0x0324) // POLYGON
+			iGc->DrawPolygonL(iPointArray,numPoints,iFillRule);
+		else // POLYLINE
+			iGc->DrawPolyLine(iPointArray, numPoints);
+		}
+		break;
+	case 0x0410: // SCALEWINDOWEXT
+		{
+		TInt xMult = aArgPtr[3];
+		TInt xDiv = aArgPtr[2];
+		TInt yMult = aArgPtr[1];
+		TInt yDiv = aArgPtr[0];
+
+		if (xDiv != 0)
+			iWindowExt.iWidth = (iWindowExt.iWidth * xMult) / xDiv;
+		if (yDiv != 0)
+			iWindowExt.iHeight = (iWindowExt.iHeight * yMult) / yDiv;
+		}
+		break;
+	case 0x0412: // SCALEVIEWPORTEXT
+		{
+		if (iIgnoreViewportMetaData == EFalse)
+			{
+			TInt xMult = aArgPtr[3];
+			TInt xDiv = aArgPtr[2];
+			TInt yMult = aArgPtr[1];
+			TInt yDiv = aArgPtr[0];
+	
+			if (xDiv != 0)
+				iViewportExt.iWidth = (iViewportExt.iWidth * xMult) / xDiv;
+			if (yDiv != 0)
+				iViewportExt.iHeight = (iViewportExt.iHeight * yMult) / yDiv;
+			}
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess1010L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0415 - EXCLUDECLIPRECT
+	// 0x0419 - FLOODFILL
+
+	switch (aFunction)
+		{
+	case 0x0416: // INTERSECTCLIPRECT
+		{
+		iIntersectRegion.Clear();
+		iIntersectRegion.AddRect(ExtractRect(aArgPtr));
+
+		iIntersectRegion.Intersect(iClipRegion);
+		iGc->SetClippingRegion(&iIntersectRegion);
+		}
+		break;
+	case 0x0418: // ELLIPSE
+		iGc->DrawEllipse(ExtractRect(aArgPtr));
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess1011L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0436 - ANIMATEPALETTE
+
+	switch (aFunction)
+		{
+	case 0x041b: // RECTANGLE
+		iGc->DrawRect(ExtractRect(aArgPtr));
+		break;
+	case 0x041f: // SETPIXEL
+		{
+		CFbsBitGcWrapper* gc = CloneGcL();
+
+		gc->SetPenColor(ExtractColor(aArgPtr));
+		gc->Plot(ExtractPoint(aArgPtr + 2,EFalse));
+
+		delete gc;
+		}
+		break;
+	case 0x0429: // FRAMEREGION
+		{
+		CGraphicsObject* object1 = GraphicsObject(aArgPtr[0]);
+		CGraphicsObject* object2 = GraphicsObject(aArgPtr[1]);
+
+		if (object1 && object1->Type() == KWmfGraphicsObjectRegion &&
+			object2 && ((object2->Type() == KWmfGraphicsObjectBrush) || (object2->Type() == KWmfGraphicsObjectPatternBrush)))
+			{
+			CRectRegion* region = STATIC_CAST(CRectRegion*,object1);
+			CBrush* brush = STATIC_CAST(CBrush*,object2);
+
+			if (brush->iStyle == CGraphicsContext::ESolidBrush)
+				{
+				CFbsBitGcWrapper* gc = CloneGcL();
+
+				gc->SetPenStyle(CGraphicsContext::ESolidPen);
+				gc->SetPenColor(brush->iColor);
+				gc->SetPenSize(TSize(aArgPtr[3],aArgPtr[2]));
+				gc->SetBrushStyle(CGraphicsContext::ENullBrush);
+
+				gc->DrawRect(region->iRect);
+
+				delete gc;
+				}
+			}
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess1100L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0548 - EXTFLOODFILL
+
+	switch (aFunction)
+		{
+	case 0x0521: // TEXTOUT
+		{
+		CFbsBitGcWrapper* gc = CloneGcL();
+		CleanupStack::PushL(gc);
+
+		gc->SetPenStyle(CGraphicsContext::ESolidPen);
+		gc->SetTextPenColor();
+		if (iBkModeOpaque)
+			gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+		else
+			gc->SetBrushStyle(CGraphicsContext::ENullBrush);
+		
+		if(iRecordSizeInWords < KMinTextoutRecordSizeInWords)
+			{
+			// Invalid Textout record.
+			User::Leave(KErrCorrupt);
+			}
+		//read the count of text-string bytes. The text is padded if necessary.
+		//The count doesn't include the padded byte.
+		const TInt count = *aArgPtr++;
+		//convert into words
+		TUint stringWords = (count+1) / 2;
+		if ((KMinTextoutRecordSizeInWords + stringWords) > iRecordSizeInWords)
+			{
+			// Invalid Textout record.
+			User::Leave(KErrCorrupt);
+			}
+		const TPtrC8 text((TUint8*)aArgPtr,count);
+
+		DrawTextL(text, ExtractPoint(aArgPtr + stringWords, EFalse), gc);
+
+		CleanupStack::PopAndDestroy(gc);
+		}
+		break;
+	case 0x0538: // POLYPOLYGON
+		{
+		//check if the record size sufficient for polygon/polyline record.
+		if(iRecordSizeInWords < KWmfPolyRecordSizeInWords)
+			{
+			User::Leave(KErrCorrupt);
+			}
+		const TInt numPolygons = *aArgPtr++;
+		if (numPolygons <= 0)
+			break;
+		
+		//check if the words that contain the number of points for each polygon are within the record
+		if(iRecordSizeInWords < (KWmfPolyRecordSizeInWords  + numPolygons))
+			{
+			User::Leave(KErrCorrupt);
+			}
+		
+		//index of word that has point for polygons
+		TInt pointWord = KWmfPolyRecordSizeInWords  + numPolygons;
+		TUint16* pointArgs = aArgPtr + numPolygons;
+		for (TInt polygonIndex = 0; polygonIndex < numPolygons; polygonIndex++)
+			{
+			const TInt numPoints = aArgPtr[polygonIndex];
+			if (numPoints <= 0)
+				break;
+
+			//check if the point values are available within the record; each point needs 2 words
+			pointWord += numPoints * 2;
+			if(iRecordSizeInWords < pointWord )
+				{
+				User::Leave(KErrCorrupt);
+				}
+
+			if (numPoints > iPointArrayEntries)
+				{
+				delete[] iPointArray;
+				iPointArray = NULL;
+				iPointArray = new(ELeave) TPoint[numPoints];
+				iPointArrayEntries = numPoints;
+				}
+
+			TPoint* pointArrayPtr = iPointArray;
+			for (TInt pointIndex = 0; pointIndex < numPoints; pointIndex++)
+				{
+				*pointArrayPtr++ = ExtractPoint(pointArgs,ETrue);
+				pointArgs += 2;
+				}
+
+			iGc->DrawPolygonL(iPointArray,numPoints,iFillRule);
+			}
+		}
+		break;
+	case 0x061c: // ROUNDRECT
+		iGc->DrawRoundRect(ExtractRect(aArgPtr + 2),ExtractPoint(aArgPtr,EFalse).AsSize());
+		break;
+	case 0x061d: // PATBLT
+		{
+		TInt left = LogicalCoordToDeviceCoord(aArgPtr[5],ETrue);
+		TInt top = LogicalCoordToDeviceCoord(aArgPtr[4],EFalse);
+		TInt width = LogicalSizeToDeviceSize(aArgPtr[3],ETrue);
+		TInt height = LogicalSizeToDeviceSize(aArgPtr[2],EFalse);
+
+		CFbsBitGcWrapper* gc = CloneGcL();
+
+		gc->SetPenStyle(CGraphicsContext::ENullPen);
+		SetROP3(gc, aArgPtr[0] | (aArgPtr[1] << 16));
+		gc->DrawRect(TRect(TPoint(left,top),TSize(width,height)));
+
+		delete gc;
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess1101L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0626 - ESCAPE
+
+	switch (aFunction)
+		{
+	case 0x06ff: // CREATEREGION
+		{
+		TInt left = LogicalCoordToDeviceCoord(aArgPtr[7],ETrue);
+		TInt top = LogicalCoordToDeviceCoord(aArgPtr[8],EFalse);
+		TInt right = LogicalCoordToDeviceCoord(aArgPtr[9],ETrue);
+		TInt bottom = LogicalCoordToDeviceCoord(aArgPtr[10],EFalse);
+
+		AddGraphicsObject(new(ELeave) CRectRegion(*iDevice, iClipRegion, left, top, right, bottom));
+		}
+		break;
+	case 0x0817: // ARC
+		iGc->DrawArc(ExtractRect(aArgPtr + 4),ExtractPoint(aArgPtr + 2,EFalse),ExtractPoint(aArgPtr,EFalse));
+		break;
+	case 0x081a: // PIE
+		iGc->DrawPie(ExtractRect(aArgPtr + 4),ExtractPoint(aArgPtr + 2,EFalse),ExtractPoint(aArgPtr,EFalse));
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess1110L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0830 - CHORD
+	// 0x0922 - BITBLT
+	// 0x0940 - DIBBITBLT
+
+	switch (aFunction)
+		{
+	case 0x0a32: // EXTTEXTOUT
+		{
+		CFbsBitGcWrapper* gc = CloneGcL();
+		CleanupStack::PushL(gc);
+
+		gc->SetPenStyle(CGraphicsContext::ESolidPen);
+		gc->SetTextPenColor();
+		if (iBkModeOpaque)
+			gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+		else
+			gc->SetBrushStyle(CGraphicsContext::ENullBrush);
+
+		const TPoint pos(ExtractPoint(aArgPtr,EFalse));
+		const TInt count = aArgPtr[2];
+		const TInt flag = aArgPtr[3];
+
+		aArgPtr += (flag & KExtTextOutFlagClipped) ? 8 : 4;
+
+		const TPtrC8 text((TUint8*)aArgPtr,count);
+
+		DrawTextL(text,pos,gc);
+
+		CleanupStack::PopAndDestroy(gc);
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DoProcess1111L(TInt aFunction,TUint16* aArgPtr)
+	{
+	// Not supported:
+	// 0x0b23 - STRETCHBLT
+	// 0x0d33 - SETDIBTODEV
+
+	switch (aFunction)
+		{
+	case 0x0b41: // DIBSTRETCHBLT
+		{
+		const TInt16* argPtr = (TInt16*)aArgPtr;
+		const TInt srcX = argPtr[5];
+		const TInt srcY = argPtr[4];
+		const TInt srcWidth = argPtr[3];
+		const TInt srcHeight = argPtr[2];
+		const TInt dstX = LogicalCoordToDeviceCoord(argPtr[9],ETrue);
+		const TInt dstY = LogicalCoordToDeviceCoord(argPtr[8],EFalse);
+		const TInt dstWidth = LogicalSizeToDeviceSize(argPtr[7],ETrue);
+		const TInt dstHeight = LogicalSizeToDeviceSize(argPtr[6],EFalse);
+
+		CFbsBitmap* dib = new(ELeave) CFbsBitmap;
+		TInt err = ExtractDib(aArgPtr + 10, dib);
+
+		CleanupStack::PushL(dib);
+		if (err == KErrNone)
+			{
+			const TRect srcRect(TPoint(srcX,srcY),TSize(srcWidth,srcHeight));
+			const TRect dstRect(TPoint(dstX,dstY),TSize(dstWidth,dstHeight));
+
+			iGc->DrawBitmap(dstRect,dib,srcRect);
+			}
+		else if (err != KErrNotSupported) // Ignore KErrNotSupported
+			User::Leave(err);
+
+		CleanupStack::PopAndDestroy(dib);
+		}
+		break;
+	case 0x0f43: // STRETCHDIB
+		{
+		const TInt16* argPtr = (TInt16*)aArgPtr;
+		const TInt srcX = argPtr[6];
+		const TInt srcY = argPtr[5];
+		const TInt srcWidth = argPtr[4];
+		const TInt srcHeight = argPtr[3];
+		const TInt dstX = LogicalCoordToDeviceCoord(argPtr[10],ETrue);
+		const TInt dstY = LogicalCoordToDeviceCoord(argPtr[9],EFalse);
+		const TInt dstWidth = LogicalSizeToDeviceSize(argPtr[8],ETrue);
+		const TInt dstHeight = LogicalSizeToDeviceSize(argPtr[7],EFalse);
+
+		CFbsBitmap* dib = new(ELeave) CFbsBitmap;
+		TInt err = ExtractDib(aArgPtr + 11, dib);
+
+		CleanupStack::PushL(dib);
+		if (err == KErrNone)
+			{
+			const TRect srcRect(TPoint(srcX,srcY),TSize(srcWidth,srcHeight));
+			const TRect dstRect(TPoint(dstX,dstY),TSize(dstWidth,dstHeight));
+
+			iGc->DrawBitmap(dstRect,dib,srcRect);
+			}
+		else if (err != KErrNotSupported) // Ignore KErrNotSupported
+			User::Leave(err);
+
+		CleanupStack::PopAndDestroy(dib);
+		}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CWmfReadCodec::DrawTextL(const TDesC8& aText, const TPoint& aPos, CFbsBitGcWrapper* aGc)
+	{
+	if(aText.Length()==0)
+		return;
+
+	HBufC* unicodeText = HBufC::NewMaxLC(aText.Length());
+	TPtr16 text = unicodeText->Des();
+	text.Copy(aText);
+
+	TPoint pos(aPos);
+	const CFbsFont* font = iGc->CurrentFont();
+
+	if (font)
+		{
+		const TInt textAlignHorz = iTextAlignFlags & KTextAlignMaskHorz;
+		const TInt textAlignVert = iTextAlignFlags & KTextAlignMaskVert;
+
+		switch (textAlignHorz)
+			{
+		case KTextAlignFlagRight:
+			pos.iX -= font->TextWidthInPixels(text);
+			break;
+		case KTextAlignFlagCenter:
+			pos.iX -= font->TextWidthInPixels(text) / 2;
+			break;
+		default: // KTextAlignFlagLeft
+			break;
+			}
+
+		// rather than use font->AscentInPixels(), font->DescentInPixels(),
+		// which don't include the height of accents etc, 
+		// use the maximum possible ascent/decent instead
+		TInt ascent;
+		TInt descent;
+		TOpenFontMetrics fontMetrics;
+		if (font->IsOpenFont() && font->GetFontMetrics(fontMetrics))
+			{
+			ascent = fontMetrics.MaxHeight();
+			descent = fontMetrics.MaxDepth();
+			}
+		else
+			{
+			ascent = font->AscentInPixels();
+			descent = font->DescentInPixels();
+			}
+
+		switch (textAlignVert)
+			{
+		case KTextAlignFlagBottom:
+			pos.iY -= descent;
+			break;
+		case KTextAlignFlagBaseline:
+			break;
+		default: // KTextAlignFlagTop
+			pos.iY += ascent;
+			break;
+			}
+		aGc->DrawText(*unicodeText,pos);
+		}
+
+	CleanupStack::PopAndDestroy(unicodeText);
+	}
+
+void CWmfReadCodec::AddGraphicsObject(CGraphicsObject* aObject)
+	{
+	for (TInt index = 0; index < KWmfMaxGraphicsObjectCount; index++)
+		{
+		if (iGraphicsObject[index] == NULL)
+			{
+			iGraphicsObject[index] = aObject;
+			return;
+			}
+		}
+
+	delete aObject; // No more space so throw the object away
+	}
+
+CGraphicsObject* CWmfReadCodec::GraphicsObject(TInt aHandle)
+	{
+	if (aHandle < KWmfMaxGraphicsObjectCount)
+		return iGraphicsObject[aHandle];
+
+	return NULL;
+	}
+
+void CWmfReadCodec::RemoveGraphicsObject(TInt aHandle)
+	{
+	if (aHandle < KWmfMaxGraphicsObjectCount)
+		{
+		CGraphicsObject* object = iGraphicsObject[aHandle];
+
+		if (object)
+			{
+			if (object->Type() == KWmfGraphicsObjectPen && !iDefaultPen)
+				iDefaultPen = STATIC_CAST(CPen*,object);
+			else if (object->Type() == KWmfGraphicsObjectBrush && !iDefaultBrush)
+				iDefaultBrush = STATIC_CAST(CBrush*,object);
+			else
+				delete object;
+
+			iGraphicsObject[aHandle] = NULL;
+			}
+		}
+	}
+
+CFbsBitGcWrapper* CWmfReadCodec::CloneGcL()
+	{
+	CFbsBitGcWrapper* gcCopy;
+	if (iMaskDevice)
+		gcCopy = CFbsBitGcMaskWrapper::NewL(*iDevice, *iMaskDevice, static_cast<CFbsBitGcMaskWrapper*> (iGc));
+	else
+		gcCopy = CFbsBitGcWrapper::NewL(*iDevice, iGc);
+
+	return gcCopy;
+	}
+
+TInt CWmfReadCodec::LogicalCoordToDeviceCoord(TInt aLogicalCoord,TBool aHorizontal)
+	{
+	if (aHorizontal)
+		{
+		if (iWindowExt.iWidth != 0)
+			return ((aLogicalCoord - iWindowOrg.iX) * iViewportExt.iWidth / iWindowExt.iWidth) + iViewportOrg.iX;
+		}
+	else
+		{
+		if (iWindowExt.iHeight != 0)
+			return ((aLogicalCoord - iWindowOrg.iY) * iViewportExt.iHeight / iWindowExt.iHeight) + iViewportOrg.iY;
+		}
+
+	return 0;
+	}
+
+TInt CWmfReadCodec::LogicalSizeToDeviceSize(TInt aLogicalSize,TBool aHorizontal)
+	{
+	if (aHorizontal)
+		{
+		if (iWindowExt.iWidth != 0)
+			return aLogicalSize * iViewportExt.iWidth / iWindowExt.iWidth;
+		}
+	else
+		{
+		if (iWindowExt.iHeight != 0)
+			return aLogicalSize * iViewportExt.iHeight / iWindowExt.iHeight;
+		}
+
+	return 0;
+	}
+
+void CWmfReadCodec::SetROP(CFbsBitGcWrapper* aGc,TInt aROP)
+	{
+	CGraphicsContext::TDrawMode drawMode = CGraphicsContext::EDrawModePEN;
+
+	switch (aROP)
+		{
+	case 1: // R2_BLACK
+		aGc->SetPenColor(KRgbBlack);
+		aGc->SetBrushColor(KRgbBlack);
+		aGc->SetDrawMode(drawMode);
+		return;
+
+	case 11: // R2_NOP
+		aGc->SetPenStyle(CGraphicsContext::ENullPen);
+		aGc->SetBrushStyle(CGraphicsContext::ENullBrush);
+		aGc->SetDrawMode(drawMode);
+		return;
+
+	case 16: // R2_WHITE
+		aGc->SetPenColor(KRgbWhite);
+		aGc->SetBrushColor(KRgbWhite);
+		aGc->SetDrawMode(drawMode);
+		return;
+
+	default:
+		break;
+		}
+
+	switch (aROP)
+		{
+	case 2:		drawMode = CGraphicsContext::EDrawModeNOTANDNOT;	break; // R2_NOTMERGEPEN
+	case 3:		drawMode = CGraphicsContext::EDrawModeANDNOT;		break; // R2_MASKNOTPEN
+	case 4:		drawMode = CGraphicsContext::EDrawModeNOTPEN;		break; // R2_NOTCOPYPEN
+	case 5:		drawMode = CGraphicsContext::EDrawModeNOTAND;		break; // R2_MASKPENNOT
+	case 6:		drawMode = CGraphicsContext::EDrawModeNOTSCREEN;	break; // R2_NOT
+	case 7:		drawMode = CGraphicsContext::EDrawModeXOR;			break; // R2_XORPEN
+	case 8:		drawMode = CGraphicsContext::EDrawModeNOTORNOT;		break; // R2_NOTMASKPEN
+	case 9:		drawMode = CGraphicsContext::EDrawModeAND;			break; // R2_MASKPEN
+	case 10:	drawMode = CGraphicsContext::EDrawModeNOTXOR;		break; // R2_NOTXORPEN
+
+	case 12:	break; // R2_MERGENOTPEN (not supported)
+	case 13:	break; // R2_COPYPEN
+	case 14:	drawMode = CGraphicsContext::EDrawModeNOTOR;		break; // R2_MERGEPENNOT
+	case 15:	drawMode = CGraphicsContext::EDrawModeOR;			break; // R2_MERGEPEN
+
+	default:
+		break;
+		}
+
+	aGc->RestorePenAndBrush();
+	aGc->SetDrawMode(drawMode);
+	}
+
+void CWmfReadCodec::SetROP3(CFbsBitGcWrapper* aGc,TInt aROP)
+	{
+	CGraphicsContext::TDrawMode drawMode = CGraphicsContext::EDrawModePEN;
+	switch (aROP)
+		{
+	case 0x005A0049: // PATINVERT
+		drawMode = CGraphicsContext::EDrawModeXOR;
+		break;
+	case 0x00550009: // DSTINVERT
+		drawMode = CGraphicsContext::EDrawModeNOTSCREEN;
+		aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+		break;
+	case 0x00000042: // BLACKNESS
+		aGc->SetBrushColor(KRgbBlack);
+		aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+		break;
+	case 0x00FF0062: // WHITENESS
+		aGc->SetBrushColor(KRgbWhite);
+		aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+		break;
+
+	case 0x00F00021: // PATCOPY
+	default:
+		break;
+		}
+
+	aGc->SetDrawMode(drawMode);
+	}
+
+TRgb CWmfReadCodec::ExtractColor(const TUint16* aArgPtr)
+	{
+	return TRgb(aArgPtr[0] & 0xff,aArgPtr[0] >> 8,aArgPtr[1] & 0xff);
+	}
+
+TPoint CWmfReadCodec::ExtractPoint(const TUint16* aArgPtr,TBool aXYOrder)
+	{
+	TInt16* coordPtr = (TInt16*)aArgPtr;
+
+	TInt left = coordPtr[0];
+	TInt top = coordPtr[1];
+
+	if (!aXYOrder)
+		{
+		TInt temp = left;
+		left = top;
+		top = temp;
+		}
+
+	left = LogicalCoordToDeviceCoord(left,ETrue);
+	top = LogicalCoordToDeviceCoord(top,EFalse);
+
+	return TPoint(left,top);
+	}
+
+TRect CWmfReadCodec::ExtractRect(const TUint16* aArgPtr)
+	{
+	TInt16* coordPtr = (TInt16*)aArgPtr;
+
+	TInt left = LogicalCoordToDeviceCoord(coordPtr[3],ETrue);
+	TInt top = LogicalCoordToDeviceCoord(coordPtr[2],EFalse);
+	TInt right = LogicalCoordToDeviceCoord(coordPtr[1],ETrue);
+	TInt bottom = LogicalCoordToDeviceCoord(coordPtr[0],EFalse);
+
+	return TRect(left,top,right,bottom);
+	}
+
+TInt CWmfReadCodec::ExtractDib(const TUint16* aArgPtr, CPatternBrush* aPatternBrush)
+	{
+	TInt bitCount = aArgPtr[7];
+	if (bitCount != 1)
+		return ExtractDib(aArgPtr, aPatternBrush->Bitmap());
+
+	TInt structSize = aArgPtr[0] | (aArgPtr[1] << 16);
+	TInt width = aArgPtr[2] | (aArgPtr[3] << 16);
+	TInt height = aArgPtr[4] | (aArgPtr[5] << 16);
+
+	// Skip biPlanes half-word
+	TInt compression = aArgPtr[8] | (aArgPtr[9] << 16);
+	if (compression)
+		return KErrNotSupported;
+
+	// Skip biSizeImage word
+	TInt xPixelsPerMeter = aArgPtr[12] | (aArgPtr[13] << 16);
+	TInt yPixelsPerMeter = aArgPtr[14] | (aArgPtr[15] << 16);
+
+	// Skip biClrUsed word
+	// Skip biClrImportant word
+
+	TUint8* bytePtr = (TUint8*)aArgPtr;
+	bytePtr += structSize;
+
+	CFbsBitmap* bitmap = aPatternBrush->Bitmap();
+	TInt err = bitmap->Create(TSize(width,height), EColor64K);
+	if (err != KErrNone)
+		return err;
+
+	TSize twipsSize(0,0);
+	if (xPixelsPerMeter > 0)
+		twipsSize.iWidth = KTwipsPerCm * 100 * width / xPixelsPerMeter;
+	if (yPixelsPerMeter > 0)
+		twipsSize.iHeight = KTwipsPerCm * 100 * height / yPixelsPerMeter;
+	bitmap->SetSizeInTwips(twipsSize);
+
+	// Skip the palette.
+	bytePtr+= 8;
+
+	// Set the pattern bits.
+	TInt padding = ((width + 31) & ~31) - width;
+	TInt byteTotal = ((width+padding)*height)/8;
+	TUint8* bitmapBits = new TUint8[byteTotal];
+	if (!bitmapBits)
+		return KErrNoMemory;
+
+	Mem::Copy(bitmapBits, bytePtr, byteTotal);
+	aPatternBrush->SetBitmapBits(bitmapBits);
+	return KErrNone;
+	}
+
+TInt CWmfReadCodec::ExtractDib(const TUint16* aArgPtr, CFbsBitmap* aBitmap)
+	{
+	const TInt structSize = aArgPtr[0] | (aArgPtr[1] << 16);
+	const TInt width = aArgPtr[2] | (aArgPtr[3] << 16);
+	const TInt height = aArgPtr[4] | (aArgPtr[5] << 16);
+
+	// Skip biPlanes half-word
+	const TInt bitCount = aArgPtr[7];
+	const TInt compression = aArgPtr[8] | (aArgPtr[9] << 16);
+	if (((bitCount != 24) && (bitCount != 8) && (bitCount != 1)) || compression)
+		return KErrNotSupported;
+
+	// Skip biSizeImage word
+	const TInt xPixelsPerMeter = aArgPtr[12] | (aArgPtr[13] << 16);
+	const TInt yPixelsPerMeter = aArgPtr[14] | (aArgPtr[15] << 16);
+
+	// Skip biClrUsed word
+	// Skip biClrImportant word
+
+	TUint8* bytePtr = (TUint8*)aArgPtr;
+	bytePtr += structSize;
+
+	TInt err = aBitmap->Create(TSize(width,height), EColor64K);
+	if (err != KErrNone)
+		return err;
+
+	TSize twipsSize(0,0);
+	if (xPixelsPerMeter > 0)
+		twipsSize.iWidth = KTwipsPerCm * 100 * width / xPixelsPerMeter;
+	if (yPixelsPerMeter > 0)
+		twipsSize.iHeight = KTwipsPerCm * 100 * height / yPixelsPerMeter;
+	aBitmap->SetSizeInTwips(twipsSize);
+
+	TBitmapUtil util(aBitmap);
+	if (bitCount == 24)
+		{
+		TInt byteWidth = 3*width;
+		TInt padding = ((byteWidth + 3) & ~3) - byteWidth;
+		for (TInt y = height - 1; y >= 0; y--)
+			{
+			util.Begin(TPoint(0,y));
+			for (TInt x = 0; x < width; x++)
+				{
+				TRgb color(bytePtr[2],bytePtr[1],bytePtr[0]);
+				util.SetPixel(color.Color64K());
+				util.IncXPos();
+				bytePtr += 3;
+				}
+			bytePtr += padding;
+			util.End();
+			}
+		}
+	else if (bitCount == 8)
+		{
+		// Read the palette.
+		TRgb* palette = new TRgb[256];
+		if (!palette)
+			return KErrNoMemory;
+
+		for (TInt count = 0; count < 256; count++)
+			{
+			TInt blue = bytePtr[0];
+			TInt green = bytePtr[1];
+			TInt red = bytePtr[2];
+			
+			bytePtr += 4; // Skip rgbReserved
+			palette[count] = TRgb(red, green, blue);
+			}
+
+		const TInt padding = ((width + 3) & ~3) - width;
+		for (TInt y = height - 1; y >= 0; y--)
+			{
+			util.Begin(TPoint(0,y));
+			for (TInt x = 0; x < width; x++)
+				{
+				TRgb color(palette[bytePtr[0]]);
+				util.SetPixel(color.Color64K());
+				util.IncXPos();
+				bytePtr++;
+				}
+			bytePtr += padding;
+			util.End();
+			}
+
+		delete[] palette;
+		}
+	else // 1bpp
+		{
+		// Read the palette.
+		TRgb palette[2];
+		for (TInt count = 0; count < 2; count++)
+			{
+			TInt blue = bytePtr[0];
+			TInt green = bytePtr[1];
+			TInt red = bytePtr[2];
+			
+			bytePtr += 4; // Skip rgbReserved
+			palette[count] = TRgb(red, green, blue);
+			}
+
+		const TInt padding = ((width + 31) & ~31) - width;
+		TUint pixelMask = 0x80;
+		for (TInt y = height - 1; y >= 0; y--)
+			{
+			util.Begin(TPoint(0,y));
+
+			TInt x;
+			for (x = 0; x < width; x++)
+				{
+				TRgb color(palette[(bytePtr[0] & pixelMask) ? 1 : 0]);
+				util.SetPixel(color.Color64K());
+				util.IncXPos();
+
+				pixelMask >>= 1;
+				if (pixelMask == 0)
+					{
+					pixelMask = 0x80;
+					bytePtr++;
+					}
+				}
+
+			for (x = 0 ; x<padding ; x++)
+				{
+				pixelMask >>= 1;
+				if (pixelMask == 0)
+					{
+					pixelMask = 0x80;
+					bytePtr++;
+					}
+				}
+
+			util.End();
+			}
+		}
+
+	return KErrNone;
+	}
+
+TInt CWmfReadCodec::ReducedSize(const TSize& aOriginalSize,TInt aReductionFactor, TSize& aReducedSize) const
+	{
+	aReducedSize = aOriginalSize;
+   	if (aReductionFactor<0)
+   	   {
+   	   return KErrArgument;
+   	   }
+   	TInt roundup = aReductionFactor>0? 1<<(aReductionFactor-1): 0;
+   	aReducedSize.SetSize(((aOriginalSize.iWidth+roundup)>>aReductionFactor),
+               ((aOriginalSize.iHeight+roundup)>>aReductionFactor) );
+    return KErrNone;            
+	}
+
+TInt CWmfReadCodec::ReductionFactor(const TSize& aOriginalSize, const TSize& aReducedSize) const
+	{
+	if( (aReducedSize.iWidth<=0) || (aReducedSize.iHeight<=0))
+      	{
+      	return 0;
+		}
+   	TInt reductionFactor = 0;
+   	TInt roundup=0;
+	while( ((aOriginalSize.iWidth+roundup)>>reductionFactor) > aReducedSize.iWidth || 
+         ((aOriginalSize.iHeight+roundup)>>reductionFactor) > aReducedSize.iHeight)
+    	{
+      	reductionFactor++;
+      	roundup=1<<(reductionFactor-1);
+    	}
+	return reductionFactor;
+	}
+
+void CWmfReadCodec::SetIgnoreViewportMetaData(TBool aIgnoreViewportMetaData)
+	{
+	iIgnoreViewportMetaData = aIgnoreViewportMetaData;
+	}