graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdibitblt.cpp
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdibitblt.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1358 @@
+// Copyright (c) 2007-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 "swdirectgdiengine.h"
+#include "swdirectgdidriverimpl.h"
+#include "directgdiadapter.h"
+#include <bitdrawinterfaceid.h>
+#include <bmalphablend.h>
+#include <graphics/bitmap.inl>
+#include <graphics/gdi/gdiinline.inl>
+
+/** 
+@see MDirectGdiEngine::BitBlt()
+@panic DGDIAdapter 7, aBitmap is invalid (debug only). 
+*/
+void CSwDirectGdiEngine::BitBlt(const TPoint& aDestPos, 
+								const CFbsBitmap& aBitmap,	
+								const TRect& aSrceRect)
+	{
+	if (aBitmap.ExtendedBitmapType() != KNullUid)
+		{
+		iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps
+		return;
+		}
+	
+	TRect srceRect(aSrceRect);
+	const TPoint destPoint(aDestPos + iOrigin + srceRect.iTl - aSrceRect.iTl);
+	const TPoint offset(srceRect.iTl - destPoint);
+
+	TRect targetRect(destPoint,srceRect.Size());
+	aBitmap.BeginDataAccess();
+
+	CBitwiseBitmap* srce = static_cast<const CSwDirectGdiBitmap&>(aBitmap).Address();
+	GRAPHICS_ASSERT_DEBUG(srce,EDirectGdiPanicInvalidBitmap);
+	
+	const TInt limit = iDefaultRegionPtr->Count();		
+			
+	TBool opaqueSource = (!IsAlphaChannel(aBitmap.DisplayMode())) && (iDrawMode == DirectGdi::EDrawModePEN);	
+
+	TRect clipRect;
+	for (TInt count = 0; count < limit; count++)
+		{
+		clipRect = (*iDefaultRegionPtr)[count];
+		if(!clipRect.Intersects(targetRect))
+			{
+			continue;
+			}
+		
+		clipRect.Intersection(targetRect);
+		
+		TRect clippedSrceRect(clipRect);
+		clippedSrceRect.Move(offset);
+
+		if (opaqueSource)
+			{
+			iDrawMode = DirectGdi::EDrawModeWriteAlpha; // write rather than blend.
+			}		
+		
+		DoBitBlt(clipRect.iTl, srce, aBitmap.DataAddress(), aBitmap.DataStride(), clippedSrceRect);
+		
+		if (opaqueSource)
+			{
+			iDrawMode = DirectGdi::EDrawModePEN; // set it back to how it was.
+			}
+		
+		iDrawDevice->UpdateRegion(clipRect);
+		}
+	
+	aBitmap.EndDataAccess(ETrue);	
+	}
+
+/**
+@see MDirectGdiEngine::BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, TBool)
+@panic DGDIAdapter 7, if either aMaskBitmap or aBitmap are invalid (debug only).
+*/
+void CSwDirectGdiEngine::BitBltMasked(const TPoint& aDestPos,
+			  const CFbsBitmap& aBitmap,
+			  const TRect& aSrcRect,
+			  const CFbsBitmap& aMaskBitmap,
+			  TBool aInvertMask)
+	{
+	if ((aBitmap.ExtendedBitmapType() != KNullUid) || (aMaskBitmap.ExtendedBitmapType() != KNullUid))
+		{
+		iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps
+		return;
+		}
+	
+	TRect localSrcRect(aSrcRect);
+	const TPoint destPoint(aDestPos + iOrigin + localSrcRect.iTl - aSrcRect.iTl);
+	const TRect destRect(destPoint, localSrcRect.Size());
+	const TPoint offset(localSrcRect.iTl - destPoint);
+	
+	TRect targetRect(destRect);
+	aBitmap.BeginDataAccess();
+	aMaskBitmap.BeginDataAccess();
+	
+	CBitwiseBitmap* srcebmp = static_cast<const CSwDirectGdiBitmap&>(aBitmap).Address();
+	CBitwiseBitmap* maskbmp = static_cast<const CSwDirectGdiBitmap&>(aMaskBitmap).Address();		
+	
+	GRAPHICS_ASSERT_DEBUG(srcebmp,EDirectGdiPanicInvalidBitmap);
+	GRAPHICS_ASSERT_DEBUG(maskbmp,EDirectGdiPanicInvalidBitmap);
+	
+	const TDisplayMode maskMode = maskbmp->DisplayMode();
+	const TInt limit = iDefaultRegionPtr->Count();
+	TBool opaqueSource = (!IsAlphaChannel(aBitmap.DisplayMode())) && (iDrawMode == DirectGdi::EDrawModePEN);
+	TRect clipRect;
+	for (TInt count = 0; count < limit; count++)
+		{
+		clipRect = (*iDefaultRegionPtr)[count];
+		if (!clipRect.Intersects(targetRect))
+			{
+			continue;
+			}
+		
+		clipRect.Intersection(targetRect);
+		TRect clippedSrceRect(clipRect);
+		clippedSrceRect.Move(offset);
+		
+		if (opaqueSource)
+			{
+			iDrawMode = DirectGdi::EDrawModeWriteAlpha; // ie write rather than blend
+			}
+		
+		DoBitBltMasked(clipRect.iTl, srcebmp, aBitmap.DataAddress(), clippedSrceRect, maskbmp, 
+				aMaskBitmap.DataAddress(), aInvertMask);
+		
+		if (opaqueSource)
+			{
+			iDrawMode = DirectGdi::EDrawModePEN; // set to default
+			}
+		iDrawDevice->UpdateRegion(clipRect);
+		}
+	
+	aBitmap.EndDataAccess(ETrue);
+	aMaskBitmap.EndDataAccess(ETrue);	
+	}
+
+
+/**
+@see MDirectGdiEngine::BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, const TPoint&)
+@panic DGDIAdapter 7, if either aBitmap or aMaskBitmap are invalid.
+@panic DGDIAdapter 1022, if the top-left corner of aSrcRect is out of bounds (debug only).
+*/
+void CSwDirectGdiEngine::BitBltMasked(const TPoint& aDestPt,
+		const CFbsBitmap& aBitmap, const TRect& aSrcRect,
+		const CFbsBitmap& aMaskBitmap, const TPoint& aAlphaPt)
+	{
+	if ((aBitmap.ExtendedBitmapType() != KNullUid) || (aMaskBitmap.ExtendedBitmapType() != KNullUid))
+		{
+		iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps
+		return;
+		}
+	
+	TRect srcRect(aSrcRect);
+	//Calculate the destination rect
+	TPoint destPt(aDestPt + iOrigin);
+	TRect destRect(destPt, srcRect.Size());
+	TPoint offset(srcRect.iTl - destPt);
+	TRect targetRect(destRect);
+
+	aBitmap.BeginDataAccess();
+	aMaskBitmap.BeginDataAccess();
+	CBitwiseBitmap* srcBmp = static_cast<const CSwDirectGdiBitmap&>(aBitmap).Address();
+	CBitwiseBitmap* alphaBmp = static_cast<const CSwDirectGdiBitmap&>(aMaskBitmap).Address();
+	GRAPHICS_ASSERT_DEBUG(srcBmp, EDirectGdiPanicInvalidBitmap);
+	GRAPHICS_ASSERT_DEBUG(alphaBmp, EDirectGdiPanicInvalidBitmap);
+	TUint32* srcDataAddr = aBitmap.DataAddress();
+	TUint32* alphaDataAddr = aMaskBitmap.DataAddress();
+
+	//For each region - find the clipping rect and draw
+	TInt limit = iDefaultRegionPtr->Count ();
+	TRect clipRect;
+	for (TInt count=0; count<limit;count++)
+		{
+		clipRect=(*iDefaultRegionPtr)[count];
+		if ( !clipRect.Intersects(targetRect))
+			{
+			continue;
+			}
+		//targetRect was constructed from destRect. destRect was constructed from srcRect.
+		clipRect.Intersection (targetRect);
+		TRect clippedSrcRect(clipRect);
+		clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect now.
+		TPoint shift(clippedSrcRect.iTl - srcRect.iTl);
+		GRAPHICS_ASSERT_DEBUG(shift.iX >= 0, EDirectGdiPanicNegativeShift);
+		GRAPHICS_ASSERT_DEBUG(shift.iY >= 0, EDirectGdiPanicNegativeShift);
+		DoBitBltAlpha (clipRect.iTl, srcBmp, srcDataAddr, clippedSrcRect,
+				alphaBmp, alphaDataAddr, aAlphaPt + shift, EFalse);
+		iDrawDevice->UpdateRegion (clipRect);
+		}
+
+	aBitmap.EndDataAccess(ETrue);
+	aMaskBitmap.EndDataAccess(ETrue);
+	return;
+	}			
+
+/** 
+Calculates the position into the scanline for the given x coordinate.
+
+@param aX The given x-coordinate.
+@param aDisplayMode The applied display mode.
+@return The memory offset, or 0 if the mode is not supported.
+@panic DGDIAdapter 1009, if aDisplayMode is not supported (debug only).
+*/
+TUint CSwDirectGdiEngine::MemoryOffsetForPixelPitch(TUint aX, TDisplayMode aDisplayMode) const
+	{	
+	switch (aDisplayMode)
+		{
+		case EColor16MU:
+		case EColor16MAP:
+			return aX << 2;
+		case EColor64K:
+			return aX << 1;
+		default:
+			GRAPHICS_PANIC_DEBUG(EDirectGdiPanicInvalidDisplayMode);
+		}
+	return 0;
+	}
+
+TUint32* CSwDirectGdiEngine::GetScanLineOffsetPtr(CBitwiseBitmap* aSrce, TUint32*& aSlptr, 
+		TInt aLength, TPoint aPixel, TUint32* aBase, 
+		TLineScanningPosition& aLineScanningPosition, TUint aXOffset)
+	{
+	aSrce->GetScanLinePtr(aSlptr, aLength, aPixel, aBase, aLineScanningPosition);
+	return (TUint32*)((TUint8*)aSlptr + aXOffset);
+	}
+
+/**
+Performs the actual bitblt to the device.
+This function may also be called by DrawBitmap(), and DrawRect() when using a patterned brush, 
+so any changes to this function may impact on them also.
+
+@pre aSrce A bitmap with non-zero dimensions. aSrceRect has been clipped against the target.
+
+@param aDest The target position on the device which will contain the top left 
+             corner of the source bitmap.
+@param aSrce The bitmap object that contains the pixels to draw.
+@param aBase The address of the bitmap pixels.
+@param aStride The length in bytes between scanlines in memory.
+@param aSrceRect The area of the bitmap to draw from.
+@panic DGDIAdapter 1013, if aDest is fully outside of the bounds of the target, or aSrceRect.iTl is not
+       within the drawing area (debug only).
+*/
+void CSwDirectGdiEngine::DoBitBlt(const TPoint& aDest,
+		 CBitwiseBitmap* aSrce,
+		 TUint32* aBase,
+		 TInt aStride,
+		 const TRect& aSrceRect)
+	{
+	// Does multiple bitmap widths for painting rects only
+	const TInt width = aSrceRect.Width ();
+
+#ifdef _DEBUG
+	TRect deviceDestRect;
+	iDrawDevice->GetDrawRect(deviceDestRect);
+	GRAPHICS_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG((aDest.iX + aSrceRect.Width()) <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG((aDest.iY + aSrceRect.Height()) <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG(aDest.iX >= 0 && aDest.iY >= 0, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG(aSrceRect.iTl.iX >= 0 && aSrceRect.iTl.iY >= 0, EDirectGdiPanicOutOfBounds);
+#endif
+
+	TSize srcSize = aSrce->SizeInPixels ();
+	
+	const TPoint KZeroPoint(0,0);
+	TAny* interface = NULL;
+	if (iDrawMode == DirectGdi::EDrawModeWriteAlpha &&
+			aSrceRect.iBr.iX <= srcSize.iWidth && 
+			aSrceRect.iBr.iY <= srcSize.iHeight &&
+			!aSrce->IsCompressed() && 
+			aSrce->DisplayMode() == iDrawDevice->DisplayMode() && 
+			iDrawDevice->GetInterface(KFastBlit2InterfaceID, interface) == KErrNone)
+		{
+		// Conditions in CFbsBitGc allow for optimised blitting.
+		// The draw device supports the optimised blitting function.
+		// Operation may fail regardless due to unacceptable conditions in the draw device.
+		MFastBlit2* fastBlit = reinterpret_cast<MFastBlit2*>(interface);
+		if (fastBlit && (fastBlit->WriteBitmapBlock(aDest, aBase, aStride, srcSize, aSrceRect) == KErrNone))			
+			{
+			return;
+			}			
+		}
+
+	MFastBlend* fastBlend=NULL;
+	if (FastBlendInterface(aSrce,NULL,fastBlend)==KErrNone)
+		{
+		if (fastBlend->FastBlendBitmap(aDest, aBase, aStride, srcSize, aSrceRect, aSrce->DisplayMode(), GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)== KErrNone)
+			{
+			return;
+			}
+		}
+	
+	const TInt scanLineBytes = iDrawDevice->ScanLineBytes();
+	TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
+	TPtr8 scanLineDes((TUint8*)scanLineBuffer, scanLineBytes, scanLineBytes);
+
+	const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
+	
+	const TBool useScanLinePtr = (dispMode == aSrce->DisplayMode()) && 
+		(TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode) >= 8);
+
+	TUint32* slptr = NULL;
+	TUint offset = 0;
+	TUint32* lastScanLine = NULL;
+	if (useScanLinePtr)
+		{
+		lastScanLine = aSrce->ScanLineAddress(aBase, aSrceRect.iBr.iY-1);
+		}
+
+	TInt srceWidth = srcSize.iWidth;
+	TInt partlinestart = aSrceRect.iTl.iX % srceWidth;
+	
+	if (partlinestart < 0)
+		{
+		partlinestart += srceWidth;
+		}
+	
+	const TInt partlinelength = Min(srceWidth - partlinestart, width);
+	TInt destX = aDest.iX;
+	const TInt destXlimit = destX+width;
+	const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
+
+	// first part line
+	if (partlinestart > 0 && partlinelength > 0)
+		{
+		TPoint srcecoord1(partlinestart, aSrceRect.iTl.iY);
+		TInt desty = aDest.iY;
+
+		TLineScanningPosition lineScanPos(aBase);
+
+		if (useScanLinePtr)
+			{
+			offset = MemoryOffsetForPixelPitch(partlinestart, dispMode);
+			if (aSrce->IsCompressed ())
+				{
+				
+				while (srcecoord1.iY < aSrceRect.iBr.iY)
+					{
+					scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr,
+							partlinelength, srcecoord1, aBase, lineScanPos, offset);
+					if (srcecoord1.iY == aSrceRect.iTl.iY)
+						{
+						aSrce->SetCompressionBookmark(lineScanPos, aBase, NULL);
+						}
+					iDrawDevice->WriteLine(aDest.iX, desty, partlinelength,
+							scanLineBuffer, drawMode);
+					srcecoord1.iY++;
+					desty++;				
+					}
+				}
+			else
+				{
+				while (srcecoord1.iY < aSrceRect.iBr.iY)
+					{
+					scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr,
+							partlinelength, srcecoord1, aBase, lineScanPos,
+							offset);
+					do
+						{
+						iDrawDevice->WriteLine (aDest.iX, desty,
+								partlinelength, scanLineBuffer, drawMode);
+						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride);
+						srcecoord1.iY++;
+						desty++;
+						}
+					while ((srcecoord1.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine)) ;
+					}
+				}
+			}
+		else
+			{
+			for ( ; srcecoord1.iY < aSrceRect.iBr.iY; srcecoord1.iY++, desty++)
+				{
+				aSrce->GetScanLine (scanLineDes, srcecoord1, partlinelength,
+						EFalse, KZeroPoint, dispMode, aBase, lineScanPos);
+				if ( srcecoord1.iY==aSrceRect.iTl.iY)
+					{
+					aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL);
+					}
+				iDrawDevice->WriteLine (aDest.iX, desty, partlinelength,
+						scanLineBuffer, drawMode);
+				}
+			}
+
+		destX += partlinelength;
+		}
+
+	// multiple complete lines - columns
+	TInt numcolumns = (destXlimit - destX) / srceWidth;
+	
+	if (numcolumns > 0)
+		{
+		TPoint srcecoord2(0, aSrceRect.iTl.iY);
+		TInt desty = aDest.iY;
+
+		TLineScanningPosition lineScanPos(aBase);
+
+		if (useScanLinePtr)
+			{
+			if (aSrce->IsCompressed())
+				{
+				while (srcecoord2.iY < aSrceRect.iBr.iY)
+					{
+					TPoint coord(srcecoord2);
+					aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos);
+					if (srcecoord2.iY == aSrceRect.iTl.iY)
+						{
+						aSrce->SetCompressionBookmark(lineScanPos, aBase, NULL);
+						}
+					TInt tempdestX = destX;
+					for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth)
+						{
+						iDrawDevice->WriteLine(tempdestX, desty, srceWidth, slptr, drawMode);
+						}
+					srcecoord2.iY++;
+					desty++;
+					}
+				}
+			else
+				{
+				while (srcecoord2.iY < aSrceRect.iBr.iY)
+					{
+					TPoint coord(srcecoord2);
+					aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos);
+					do
+						{
+						TInt tempdestX = destX;
+						for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth)
+							{
+							iDrawDevice->WriteLine (tempdestX, desty, srceWidth, slptr, drawMode);
+							}
+						slptr = (TUint32*)((TUint8*)slptr + aStride);
+						srcecoord2.iY++;
+						desty++;
+						}
+					while ((srcecoord2.iY < aSrceRect.iBr.iY) && (slptr < lastScanLine));
+					}
+				}
+			}
+		else
+			{
+			for (; srcecoord2.iY < aSrceRect.iBr.iY; srcecoord2.iY++, desty++)
+				{
+				TInt tempdestX = destX;
+				TPoint coord(srcecoord2);
+				aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos);
+				if (srcecoord2.iY == aSrceRect.iTl.iY)
+					{
+					aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL);
+					}
+				for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth)
+					{
+					aSrce->GetScanLine(slptr, scanLineDes, coord, srceWidth,
+							EFalse, KZeroPoint, dispMode);
+					iDrawDevice->WriteLine(tempdestX, desty, srceWidth, scanLineBuffer, drawMode);
+					}
+				}
+			}
+
+		destX += numcolumns * srceWidth;
+		}
+
+	// final part line
+	if (destX < destXlimit)
+		{
+		const TInt restofline = destXlimit - destX;
+		TPoint srcecoord3(0, aSrceRect.iTl.iY);
+		TInt desty = aDest.iY;
+
+		TLineScanningPosition lineScanPos(aBase);
+
+		if (useScanLinePtr)
+			{
+			offset = 0;
+			if (aSrce->IsCompressed())
+				{
+				while (srcecoord3.iY < aSrceRect.iBr.iY)
+					{
+					scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr,
+							srceWidth, srcecoord3, aBase, lineScanPos, offset);
+					if (srcecoord3.iY == aSrceRect.iTl.iY)
+						{
+						aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL);
+						}
+					iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode);
+					srcecoord3.iY++;
+					desty++;
+					}
+				}
+			else
+				{
+				while (srcecoord3.iY < aSrceRect.iBr.iY)
+					{
+					scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr,
+							srceWidth, srcecoord3, aBase, lineScanPos, offset);
+					do
+						{
+						iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode);
+						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride);
+						srcecoord3.iY++;
+						desty++;
+						}
+					while ((srcecoord3.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
+					}
+				}
+			}
+		else
+			{
+			for (; srcecoord3.iY < aSrceRect.iBr.iY; srcecoord3.iY++, desty++)
+				{
+				aSrce->GetScanLine (scanLineDes, srcecoord3, srceWidth, EFalse,
+						KZeroPoint, dispMode, aBase, lineScanPos);
+				if (srcecoord3.iY == aSrceRect.iTl.iY)
+					{
+					aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL);
+					}
+				iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode);
+				}
+			}
+		}
+	}
+/** 
+Performs the masked bitblt to the device.
+
+@param aDest The target position on the device which will contain the top left 
+             corner of the source bitmap.
+@param aSourceBitmap The bitmap object that contains the pixels to draw.
+@param aSourceBase The address of the source bitmap pixels.
+@param aSourceRect The area of the bitmap to draw from.
+@param aMaskBitmap The bitmap object that contains the mask.
+@param aMaskBase The address of the mask pixels.
+@param aInvertMask Inverts the mask if ETrue.
+@panic DGDIAdapter 1013, if aDest is outside of the device bounds (debug only).
+*/
+void CSwDirectGdiEngine::DoBitBltMasked(const TPoint& aDest,
+		   CBitwiseBitmap* aSourceBitmap,
+		   TUint32* aSourceBase,
+		   const TRect& aSourceRect,
+		   CBitwiseBitmap* aMaskBitmap,
+		   TUint32* aMaskBase,
+		   TBool aInvertMask)
+	{
+#ifdef _DEBUG
+	TRect deviceDestRect;
+	iDrawDevice->GetDrawRect (deviceDestRect);
+#endif
+	
+    GRAPHICS_ASSERT_DEBUG (aDest.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG (aDest.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG ((aDest.iX + aSourceRect.Width()) <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG ((aDest.iY + aSourceRect.Height()) <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds);	
+	const TPoint KZeroPoint(0,0);
+
+	MFastBlend* fastBlend=NULL;
+	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
+		{
+		if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(),
+							aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aSourceRect.iTl, aInvertMask,
+							GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone)
+			{
+			return;
+			}
+		}
+	
+	if (aMaskBitmap->DisplayMode() == EGray256)
+		{
+		DoBitBltAlpha (aDest, aSourceBitmap, aSourceBase, aSourceRect,
+				aMaskBitmap, aMaskBase, aSourceRect.iTl, EFalse);
+		}
+	// if screen driver is 16MAP we avoid logical operator pen modes by using DoBitBltAlpha() for blitting
+	else if(iDrawDevice->ScanLineDisplayMode() == EColor16MAP)
+		{
+		DoBitBltAlpha (aDest, aSourceBitmap, aSourceBase, aSourceRect,
+				aMaskBitmap, aMaskBase, aSourceRect.iTl, aInvertMask);
+		}
+	else if (aSourceBitmap == aMaskBitmap)
+		{
+		const TInt width = aSourceRect.Width();
+		const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
+		const CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeOR;
+		TPoint srcePoint(aSourceRect.iTl);
+		TInt destY = aDest.iY;
+		
+		TLineScanningPosition lineScanPos(aSourceBase);
+
+		const TBool useScanLinePtr = (dispMode == aSourceBitmap->DisplayMode() && 
+				(TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8));
+
+		if (useScanLinePtr)
+			{
+			TUint32* scanLineBuffer = NULL;
+			TUint32* slptr = NULL;
+			TUint offset = MemoryOffsetForPixelPitch (srcePoint.iX, dispMode);
+
+			if (aSourceBitmap->IsCompressed())
+				{
+				for ( ; srcePoint.iY < aSourceRect.iBr.iY; destY++,
+						srcePoint.iY++)
+					{
+					scanLineBuffer = GetScanLineOffsetPtr (
+							aSourceBitmap, slptr, width, srcePoint,
+							aSourceBase, lineScanPos, offset);
+					
+					iDrawDevice->WriteLine (aDest.iX, destY, width,
+							scanLineBuffer, drawMode);
+					}
+				}
+			else
+				{
+				TUint stride = aSourceBitmap->DataStride ();
+				TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase, aSourceRect.iBr.iY-1);
+
+				while (srcePoint.iY < aSourceRect.iBr.iY)
+					{
+					scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint,
+							aSourceBase, lineScanPos, offset);
+					do
+						{
+						iDrawDevice->WriteLine (aDest.iX, destY, width, scanLineBuffer, drawMode);
+						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + stride);
+						destY++;
+						srcePoint.iY++;
+						}
+					while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
+					}
+				}
+			}
+		else
+			{
+			const TInt scanLineBytes = iDrawDevice->ScanLineBytes();
+			TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
+			TPtr8 scanLineDes((TUint8*)scanLineBuffer, scanLineBytes,
+					scanLineBytes);
+			for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,
+					srcePoint.iY++)
+				{
+				aSourceBitmap->GetScanLine (scanLineDes, srcePoint,
+						width, EFalse, KZeroPoint, dispMode,
+						aSourceBase, lineScanPos);
+
+				iDrawDevice->WriteLine (aDest.iX, destY, width,
+						scanLineBuffer, drawMode);
+				}
+			}
+		}
+	else
+		{
+		DoBitBltMaskedFlicker(aDest, aSourceBitmap, aSourceBase,
+				aSourceRect, aMaskBitmap, aMaskBase, aInvertMask);		
+		}
+	}
+		
+/**
+@see DoBitBltMasked()
+ */
+void CSwDirectGdiEngine::DoBitBltMaskedFlicker(const TPoint& aDest,
+				  CBitwiseBitmap* aSourceBitmap,
+				  TUint32* aSourceBase,
+				  const TRect& aSourceRect,
+				  CBitwiseBitmap* aMaskBitmap,
+				  TUint32* aMaskBase,
+				  TBool aInvertMask)
+	{
+	const TInt width = aSourceRect.Width();
+	TInt destY = aDest.iY;
+	TPoint srcePoint(aSourceRect.iTl);
+	
+	TLineScanningPosition lineScanPos(aSourceBase);
+	TLineScanningPosition lineScanPosMask(aMaskBase);
+	
+	const TDisplayMode srcFormat = aSourceBitmap->DisplayMode();
+	const TDisplayMode maskFormat = aMaskBitmap->DisplayMode();
+	
+	if (aMaskBitmap->IsCompressed()) 
+		{ 
+		HBufC8* hBuf = CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride() + 4);
+		if (!hBuf) 
+			{
+			iDriver->SetError(KErrNoMemory);
+			return; // Out of memory so do not draw anything 
+			}
+		lineScanPosMask.iScanLineBuffer = hBuf; 
+		} 
+	
+	TAny* interface = NULL;
+	if ( (srcFormat == EColor16MU || srcFormat == EColor64K ) &&
+			maskFormat == EGray2 && 
+			aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
+			aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
+			iDrawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
+		{
+		// Parameters allow optimised code path
+		TInt length = width;
+		TUint32* srcPtr=NULL;
+		TUint32* maskPtr=NULL;
+		MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
+		while (srcePoint.iY < aSourceRect.iBr.iY)
+			{
+			aSourceBitmap->GetScanLinePtr(srcPtr, length, srcePoint, aSourceBase, lineScanPos);
+			aMaskBitmap->GetScanLinePtr(maskPtr, length, srcePoint, aMaskBase, lineScanPosMask);
+			
+			fastBlit->WriteMaskLineEx(aDest.iX,destY,length,srcePoint.iX,srcPtr,srcFormat,srcePoint.iX,maskPtr,aInvertMask);
+			
+			destY++;
+			++srcePoint.iY;
+			}
+		return;
+		}
+	
+	const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
+	const CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeANDNOT;
+	
+	TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
+	const TInt scanLineBytes = iDrawDevice->ScanLineBytes();
+	TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
+	TLineScanningPosition lineScanPos2(aSourceBase);
+	const TPoint KZeroPoint(0,0);
+	
+	//scanline modifications required if using different modes, bits per pixel less than 8
+	if ( (dispMode == aSourceBitmap->DisplayMode()) && 
+			(TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8))
+		{
+		TUint offset = MemoryOffsetForPixelPitch(srcePoint.iX, dispMode);
+		TUint32* slptr=NULL;
+		//mask scanline modifications required for EInvertPen, different screen modes
+		if ((drawMode != CGraphicsContext::EDrawModeANDNOT) && (dispMode == aMaskBitmap->DisplayMode()))
+			{
+			TUint32* scanLineBufferMask = NULL;
+			//stride jumping not possible with compressed bitmaps
+			if (aSourceBitmap->IsCompressed() || aMaskBitmap->IsCompressed())
+				{
+				for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++)
+					{
+					scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer, CGraphicsContext::EDrawModeXOR);
+					scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset);
+					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode);
+					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer, CGraphicsContext::EDrawModeXOR);
+					}
+				}
+			else
+				{
+				TUint strideSrc = aSourceBitmap->DataStride();
+				TUint strideMask = aMaskBitmap->DataStride();
+				TUint32* lastScanLineSrc = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
+				TUint32* lastScanLineMask = aMaskBitmap->ScanLineAddress(aMaskBase,aSourceRect.iBr.iY-1);
+
+				while (srcePoint.iY < aSourceRect.iBr.iY)
+					{
+					scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+					scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset);
+					do
+						{
+						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
+						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode);
+						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
+						destY++;
+						srcePoint.iY++;
+						}
+					while ((srcePoint.iY < aSourceRect.iBr.iY) && 
+							(scanLineBuffer < lastScanLineSrc) && 
+							(scanLineBufferMask < lastScanLineMask)	&& 
+							((scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + strideSrc))>(TUint32*)0) && 
+							((scanLineBufferMask = (TUint32*)((TUint8*)scanLineBufferMask + strideMask))>(TUint32*)0) );
+					}
+				}
+			}
+		else
+			{
+			TUint32* scanLineBufferPtr = NULL;
+			//stride jumping not possible with compressed bitmaps
+			if (aSourceBitmap->IsCompressed())
+				{
+				for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++)
+					{
+					scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR);
+					aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint, dispMode, aMaskBase, lineScanPosMask);
+					TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
+					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR);
+					}
+				}
+			else
+				{
+				TUint stride = aSourceBitmap->DataStride();
+				TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
+				while (srcePoint.iY < aSourceRect.iBr.iY)
+					{
+					scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+					do
+						{
+						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR);
+						aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse, KZeroPoint, dispMode,aMaskBase, lineScanPosMask);
+						TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
+						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR);
+						destY++;
+						srcePoint.iY++;
+						}
+					while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBufferPtr < lastScanLine) && 
+							((scanLineBufferPtr = (TUint32*)((TUint8*)scanLineBufferPtr + stride))>(TUint32*)0));
+					}
+				}
+			}
+		}
+	else
+		{
+		for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++)
+			{
+			aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse, KZeroPoint,
+					dispMode,aSourceBase,lineScanPos);
+			
+			iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
+			aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint, dispMode,
+					aMaskBase, lineScanPosMask);
+			TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
+			iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+			aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint ,dispMode,
+					aSourceBase,lineScanPos2);		
+			
+			iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
+			}
+		}
+	}		
+				
+/**
+@see DoBitBltMasked()
+ */
+void CSwDirectGdiEngine::DoBitBltAlpha(const TPoint& aDest ,CBitwiseBitmap* aSourceBitmap,
+		TUint32* aSourceBase, const TRect& aSourceRect,
+		CBitwiseBitmap* aMaskBitmap, TUint32* aMaskBase,
+		const TPoint& aAlphaPoint, TBool aInvertMask)
+	{
+	MFastBlend* fastBlend=NULL;
+	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
+		{
+		if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(),
+							aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aAlphaPoint, aInvertMask,
+							GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone)
+			{
+			return;
+			}
+		}
+
+	const TPoint KZeroPoint(0,0);
+	const TInt KScanLineLength = 256;
+	const TInt KRgbSize = 4;
+	
+	TUint8 srceRgbBuffer[KScanLineLength * KRgbSize];
+	TUint8 maskBuffer[KScanLineLength];
+	TUint8* srceRgbBufferPtr(srceRgbBuffer);
+	
+	TPtr8 srceRgbDes(srceRgbBuffer, KScanLineLength * KRgbSize, KScanLineLength * KRgbSize);
+	TPtr8 maskDes(maskBuffer, KScanLineLength, KScanLineLength);	
+	
+	TInt srceY = aSourceRect.iTl.iY;
+	TInt destY = aDest.iY;
+	TInt alphaY = aAlphaPoint.iY;
+	
+	TLineScanningPosition lineScanPosSrc(aSourceBase);
+	TLineScanningPosition lineScanPosMask(aMaskBase);
+	TDisplayMode sourceMode = aSourceBitmap->DisplayMode();
+	
+	if (aMaskBitmap->IsCompressed())
+		{
+		HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride());
+		if (hBuf == NULL)
+			{
+			iDriver->SetError(KErrNoMemory); // Out of memory so do not draw anything
+			return;
+			}
+		lineScanPosMask.iScanLineBuffer = hBuf;
+		}
+	
+	TAny* interface = NULL;
+	if ( (sourceMode == EColor16MU || sourceMode == EColor64K) &&
+		aMaskBitmap->DisplayMode() == EGray256 && // ensure a monochrome mask isn't passed in as an alpha channel
+		aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
+		aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
+		iDrawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
+		{
+		TInt length = aSourceRect.Width();
+		const TInt srceX = aSourceRect.iTl.iX;
+		const TInt alphaX = aAlphaPoint.iX;
+		const TInt destX = aDest.iX;
+		MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
+		
+		while (srceY < aSourceRect.iBr.iY)
+			{
+			TUint32* srcPtr;
+			TUint32* maskPtr;
+			TPoint srcPoint(srceX, srceY);
+			TPoint maskPoint(alphaX, alphaY);
+			
+			aSourceBitmap->GetScanLinePtr(srcPtr, length, srcPoint, aSourceBase, lineScanPosSrc);
+			aMaskBitmap->GetScanLinePtr(maskPtr, length, maskPoint, aMaskBase, lineScanPosMask);
+			
+			fastBlit->WriteAlphaLineEx(destX, destY, length, srceX, srcPtr,
+					sourceMode, alphaX, maskPtr, MAlphaBlend::EShdwBefore);
+			srceY++;
+			destY++;
+			alphaY++;
+			}
+		
+		return;
+		}
+	
+	const TBool useScanLinePtr = ( (EColor16MA == aSourceBitmap->DisplayMode()));
+	TUint32* slptr = NULL;
+	TUint offset = 0;
+	
+	while (srceY < aSourceRect.iBr.iY)
+		{
+		TInt srceX = aSourceRect.iTl.iX;
+		TInt destX = aDest.iX;
+		TInt alphaX = aAlphaPoint.iX;
+		
+		while (srceX < aSourceRect.iBr.iX)
+			{
+			TPoint srcePoint(srceX,srceY);
+			TPoint alphaPoint(alphaX,alphaY);
+			const TInt width = Min(KScanLineLength, aSourceRect.iBr.iX - srceX);
+			
+			if (useScanLinePtr)
+				{
+				offset = MemoryOffsetForPixelPitch(srceX, EColor16MU);
+				srceRgbBufferPtr = (TUint8*)GetScanLineOffsetPtr(aSourceBitmap, slptr, width, 
+						                       srcePoint, aSourceBase, lineScanPosSrc, offset);
+				}
+			else
+				{
+				aSourceBitmap->GetScanLine(srceRgbDes,srcePoint,width,EFalse,KZeroPoint,
+						               ERgb,aSourceBase,lineScanPosSrc);
+				}
+			
+			aMaskBitmap->GetScanLine(maskDes, alphaPoint, width, EFalse, KZeroPoint,
+					                EGray256, aMaskBase, lineScanPosMask);
+			TileScanLine(maskDes, width, alphaPoint, aMaskBitmap, lineScanPosMask, aMaskBase, EGray256);
+			
+			// aInvertMask is not used for alpha channels (EGray256 mask)
+			if (aInvertMask && aMaskBitmap->DisplayMode() != EGray256)
+				{
+				for (TInt i = 0; i < width; ++i)
+					{
+					maskBuffer[i] = ~maskBuffer[i];
+					}
+				}
+			
+			iDrawDevice->WriteRgbAlphaLine(destX, destY, width, srceRgbBufferPtr, maskBuffer, GcDrawMode(iDrawMode));
+			
+			srceX += KScanLineLength;
+			destX += KScanLineLength;
+			alphaX += KScanLineLength;
+			}
+		
+		srceY++;
+		destY++;
+		alphaY++;
+		}		
+	}
+
+/**
+Tiles the scan line if its length in pixels is less than aLengthInPixels.
+
+@param aScanLine A pointer to the scan line buffer.
+@param aLengthInPixels The scan line size in pixels.
+@param aSrcPt Position of the first pixel in aMaskBitmap that should be used as a source
+              for the pixels in scan line buffer.
+@param aMaskBitmap Any additional pixels for the scan line buffer will be taken from here.
+@param aScanLinePos This argument is used for some internal optimisations. It should not be
+                    modified by the caller.
+@param aMaskBase The base address of aMaskBitmap data.
+@param aDisplayMode Any additional pixels should be taken from aMaskBitmap using aDisplayMode
+                    as an argument for GetScanLine() call.
+@panic DGDIAdapter 1021, if the memory required for the scanline is greater than the size of aScanLine (debug only).
+*/
+void CSwDirectGdiEngine::TileScanLine(TPtr8& aScanLine,
+						  TInt aLengthInPixels,
+						  const TPoint& aSrcPt,
+						  const CBitwiseBitmap* aMaskBitmap,
+						  TLineScanningPosition& aScanLinePos,
+						  TUint32* aMaskBase,
+						  TDisplayMode aDisplayMode
+						  )
+	{
+	TInt lengthInBytes = CFbsBitmap::ScanLineLength(aLengthInPixels, aDisplayMode);
+	GRAPHICS_ASSERT_DEBUG(lengthInBytes <= aScanLine.MaxLength(), EDirectGdiPanicInvalidArg);
+	TInt scanLineLength = aScanLine.Length();
+	if(scanLineLength < lengthInBytes && aSrcPt.iX > 0)
+		{
+		//If, for example, src bmp is 100 pixels width, mask bmp is 20 pixels width and src
+		//rect is (10, 0, 100, 1) -> We will read only pixels 10..19 from the first scan line
+		//of the mask bmp. We have to have 90 mask bmp pixels.
+		//So we have to make a second mask bmp read startig from pixel 0 - 10 pixels length.
+		TInt maxLen = Min(aScanLine.MaxLength() - scanLineLength, aSrcPt.iX);
+		TPtr8 maskDes2(const_cast <TUint8*> (aScanLine.Ptr()) + scanLineLength, maxLen, maxLen);
+		TPoint srcPt(0, aSrcPt.iY);
+		TPoint zeroPt(0, 0);
+		aMaskBitmap->GetScanLine(maskDes2, srcPt, maxLen, EFalse, zeroPt, aDisplayMode, aMaskBase, aScanLinePos);
+		aScanLine.SetLength(scanLineLength + maskDes2.Length());
+		scanLineLength = aScanLine.Length();
+		}
+	if(scanLineLength >= lengthInBytes || scanLineLength == 0)
+		{
+		return;
+		}
+	//If we still don't have enough mask bmp pixels - we have to tile the scan line
+	TInt repeatCnt = lengthInBytes / scanLineLength - 1;
+	TInt bytesLeft = lengthInBytes % scanLineLength;
+	const TUint8* src = aScanLine.Ptr();
+	TUint8* dest = const_cast <TUint8*> (src) + scanLineLength;
+	for(;repeatCnt>0;dest+=scanLineLength,repeatCnt--)
+		{
+		Mem::Copy(dest, src, scanLineLength);
+		}
+	if(bytesLeft)
+		{
+		Mem::Copy(dest, src, bytesLeft);
+		}
+	aScanLine.SetLength(lengthInBytes);
+	}
+
+/**
+Draws a masked rectangular section of the source bitmap and does a compress/stretch to 
+fit a given destination rectangle. It uses DoBitBltMasked() if no stretching is involved. 
+
+@see DrawBitmapMasked()
+
+@param aDestRect The target position on the device containing the top left corner of the source bitmap.
+@param aSourceBitmap The bitmap object that contains the pixels to draw.
+@param aSourceBase The address of the source bitmap pixels.
+@param aSourceRect The area of the bitmap to draw from.
+@param aMaskBitmap The bitmap object that contains the mask.
+@param aMaskBase The address of the mask pixels.
+@param aInvertMask Inverts the mask if ETrue.
+@param aClipRect A clipping rectangle.
+@panic DGDIAdapter 1013, if the clipping rectangle is fully outside of the device bounds (debug only).
+*/
+void CSwDirectGdiEngine::DoDrawBitmapMasked(const TRect& aDestRect,
+							   CBitwiseBitmap* aSourceBitmap,
+							   TUint32* aSourceBase,
+							   const TRect& aSourceRect,
+							   CBitwiseBitmap* aMaskBitmap,
+							   TUint32* aMaskBase,
+							   TBool aInvertMask,
+							   const TRect& aClipRect)
+	{
+	CFbsDrawDevice* drawDevice = iDrawDevice;
+#ifdef _DEBUG
+	TRect deviceDestRect;
+	drawDevice->GetDrawRect(deviceDestRect);
+	GRAPHICS_ASSERT_DEBUG(aClipRect.iTl.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG(aClipRect.iTl.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG(aClipRect.iBr.iX <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds);
+	GRAPHICS_ASSERT_DEBUG(aClipRect.iBr.iY <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds);
+#endif
+
+	// The clipped version of the destination rectangle
+	TRect clippedDestRect(aDestRect);
+	clippedDestRect.Intersection(aClipRect);
+
+	// If the source rectangle and the destination rectangle are same,
+	// no stretch/compress operation required, just do BitBltMasked
+	if (aDestRect.Size() == aSourceRect.Size())
+		{
+		if (!clippedDestRect.IsEmpty())
+			{
+			const TPoint destPoint(clippedDestRect.iTl);
+			clippedDestRect.Move(aSourceRect.iTl - aDestRect.iTl);
+			DoBitBltMasked(destPoint,
+						   aSourceBitmap,
+						   aSourceBase,
+						   clippedDestRect,
+						   aMaskBitmap,
+						   aMaskBase,
+						   aInvertMask);
+			}
+		return;
+		}
+
+	MFastBlend* fastBlend=NULL;
+	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
+		{
+		if (fastBlend->FastBlendBitmapMaskedScaled(aClipRect, aDestRect, aSourceRect, aSourceBase, aSourceBitmap->DataStride(),
+				aSourceBitmap->DisplayMode(),aSourceBitmap->SizeInPixels(), 
+				aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aInvertMask, 
+				GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone)
+			{
+			return;
+			}
+		}
+	
+	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+	const TInt scanLineBytes = drawDevice->ScanLineBytes();
+	TPtr8 scanLineDes(reinterpret_cast<TUint8*>(scanLineBuffer),scanLineBytes,scanLineBytes);
+
+	const TInt KScanLineLength = 256;
+	const TInt KRgbSize = 4;
+	TUint8 maskBuffer[KScanLineLength];
+
+	TUint8 sourceBuffer[KScanLineLength*KRgbSize];
+	TPtr8 sourceDes(sourceBuffer,KScanLineLength*KRgbSize,KScanLineLength*KRgbSize);
+
+	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+	CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeANDNOT;
+	// If the source bitmap and the mask bitmap are same, draw the source bitmap either
+	// with EDrawModeAND or EDrawModeOR based on aInvertMask parameter.
+	if (aSourceBitmap == aMaskBitmap)
+		{
+		drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeOR;
+		}
+
+	TLinearDDA xLine;
+	TInt bitmapXStart = 0;
+	xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
+					TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
+	xLine.JumpToYCoord2(bitmapXStart,clippedDestRect.iTl.iX);
+
+	TLinearDDA yLine;
+	TPoint yCoord(aSourceRect.iTl.iY,aDestRect.iTl.iY);
+	yLine.Construct(yCoord,TPoint(aSourceRect.iBr.iY,aDestRect.iBr.iY),TLinearDDA::ELeft);
+	TInt dummy;
+	yLine.JumpToYCoord2(dummy,clippedDestRect.iTl.iY);
+	yCoord.SetXY(dummy,clippedDestRect.iTl.iY);
+
+	const TInt srceWidth = aSourceRect.Width();
+	const TInt destWidth = aDestRect.Width();
+	const TInt clipWidth = clippedDestRect.Width();
+	const TInt clipStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX;
+	const TInt sourceBmpWidth = aSourceBitmap->SizeInPixels().iWidth;
+	const TInt maskWidth = aMaskBitmap->SizeInPixels().iWidth;
+	const TInt maskHeight = aMaskBitmap->SizeInPixels().iHeight;
+
+	TLineScanningPosition lineScanPos(aSourceBase);
+	TLineScanningPosition lineScanPos2(aSourceBase);
+	TLineScanningPosition lineScanPosMask(aMaskBase);
+
+	HBufC8* alphaBuffer = NULL;
+	TPtr8 alphaBufferDes(NULL, 0);
+	const TDisplayMode maskDisplayMode = aMaskBitmap->DisplayMode();
+
+	// Mask inversion is not supported if the original source mask format is EGray256.
+	// Note that this is only used for pre-multiplied alpha targets.
+	TUint8 maskInverter = (aInvertMask && maskDisplayMode != EGray256) ? 0xFF : 0x00;
+
+	if (aSourceBitmap != aMaskBitmap)
+		{
+		// Get buffer to be used to convert non-EGray256 masks to EGray256 when display mode is EColor16MAP
+		// or to tile the mask when the mask width is smaller than the source bitmap width.
+		if (maskDisplayMode != EGray256 && (dispMode == EColor16MAP || maskWidth < sourceBmpWidth))
+			{
+			alphaBuffer = CFbsBitmap::GetExtraBuffer(CFbsBitmap::ScanLineLength(maskWidth, EGray256));
+			if (!alphaBuffer)
+				{
+				return;  // Out of memory so do not draw anything 
+				}
+			alphaBufferDes.Set(alphaBuffer->Des());
+			}
+
+		// Get buffer to be used for decompressing compressed masks when mask is EGray256
+		if (maskDisplayMode == EGray256 && aMaskBitmap->IsCompressed())
+			{
+			HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride());
+			if (!hBuf)
+				{
+				return;  // Out of memory so do not draw anything
+				}
+			lineScanPosMask.iScanLineBuffer = hBuf;
+			}
+		}
+	const TPoint KZeroPoint(0,0);
+
+	while (yCoord.iY < clippedDestRect.iBr.iY)
+		{
+		// Draw only the source bitmap, if the source bitmap and the mask bitmap are same.
+		// else draw both the bitmaps
+		if (aSourceBitmap == aMaskBitmap)
+			{
+			aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
+								 clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
+								 srceWidth, KZeroPoint,dispMode,aSourceBase,lineScanPos);
+			if (yCoord.iY==clippedDestRect.iTl.iY)
+				aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL);
+			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode);
+			}
+		else if ((maskDisplayMode == EGray256) || (dispMode == EColor16MAP))
+			{
+			// Stretch the source bitmap and the mask bitmap for KScanLineLength as stretch length
+			// then do alpha blending for this length. If the length is more then KScanLineLength
+			// repeat it till you stretch complete destination length.
+			const TPoint startPt(bitmapXStart,yCoord.iX);
+			TInt clipWidthPart = clippedDestRect.Width();
+			TBool loopLast = ETrue;
+			if(clipWidthPart > KScanLineLength)
+				{
+				clipWidthPart = KScanLineLength;
+				loopLast = EFalse;
+				}
+			TInt clipIncStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX;
+			TInt startClip=clippedDestRect.iTl.iX;
+			TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX);
+			xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
+							TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
+			xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY);
+			TPoint srcPixel(bitmapXStart % maskWidth,yCoord.iX % maskHeight);
+			TInt spaceLeft = 0;
+			TRgb maskRgbValue;
+			TUint32* maskScanLinePtr32 = NULL;
+			TPoint currentYValue(0,srcPixel.iY);
+			aMaskBitmap->GetScanLinePtr(maskScanLinePtr32, currentYValue, maskWidth, aMaskBase, lineScanPosMask);
+			// To implement non EGray256 mask support with EColor16MAP display mode, we convert
+			// the mask to EGray256.
+			if (maskDisplayMode != EGray256) // Convert scan-line to EGray256 and set maskScanLinePtr32 to the conversion.
+				{
+				aMaskBitmap->GetScanLine(maskScanLinePtr32, alphaBufferDes, currentYValue, maskWidth, EFalse, TPoint(0, 0), EGray256);
+				maskScanLinePtr32 = (TUint32*)alphaBuffer->Ptr();
+				}
+			TUint8* maskScanLinePtr = reinterpret_cast<TUint8*>(maskScanLinePtr32);
+
+			// Outer loop over all KScanLineLengths
+			FOREVER
+				{
+				aSourceBitmap->StretchScanLine(sourceDes,startPt,clipIncStrch,clipWidthPart,destWidth,
+								aSourceRect.iTl.iX,srceWidth, KZeroPoint ,EColor16MU,aSourceBase,lineScanPos);
+				// Inner loop to tile the mask if necessary
+				spaceLeft = clipWidthPart;
+				do	{
+					srcPixel.iX = sourceDestXCoords.iX % maskWidth;
+			
+					// Invert the mask using the inversion mask.
+					maskBuffer[(sourceDestXCoords.iY-clippedDestRect.iTl.iX)%KScanLineLength]=
+						maskInverter^maskScanLinePtr[srcPixel.iX];
+					xLine.NextStep(sourceDestXCoords);
+					} while (--spaceLeft>0);
+				
+				if (yCoord.iY == clippedDestRect.iTl.iY && startClip == clippedDestRect.iTl.iX)
+					{
+					aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL);
+					aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL);
+					}
+				drawDevice->WriteRgbAlphaLine(startClip,yCoord.iY,clipWidthPart,sourceBuffer,maskBuffer, GcDrawMode(iDrawMode));
+				if (loopLast)
+					{
+					break;
+					}
+				startClip+=KScanLineLength;
+				if (clippedDestRect.iBr.iX - startClip <= KScanLineLength)
+ 					{
+					loopLast = ETrue;
+					clipWidthPart = clippedDestRect.iBr.iX - startClip;
+					}
+				clipIncStrch += KScanLineLength;
+				}
+			}
+		else
+			{
+			aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
+									 clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
+									 srceWidth, KZeroPoint ,dispMode,aSourceBase,lineScanPos2);
+			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
+
+			TInt maskXStart = bitmapXStart % maskWidth;
+			if(maskWidth < sourceBmpWidth)
+				{
+				TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX);
+				xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
+								TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
+				xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY);
+				TPoint srcPixel(maskXStart,yCoord.iX % maskHeight);
+				TInt spaceLeft = clipWidth;
+				TPoint prevSourceDestXCoords(-1,-1);
+				TRgb maskRgbValue;
+				aMaskBitmap->GetScanLine(alphaBufferDes, TPoint(0,srcPixel.iY), maskWidth, EFalse, TPoint(0, 0), EGray256, aMaskBase, lineScanPosMask);
+
+				// Loop to tile the mask
+				do	{
+					if (sourceDestXCoords.iY != prevSourceDestXCoords.iY)
+						{
+						if (sourceDestXCoords.iX != prevSourceDestXCoords.iX)
+							{
+							srcPixel.iX = sourceDestXCoords.iX % maskWidth;
+							if (srcPixel.iX < 0)
+								srcPixel.iX += maskWidth;
+							maskRgbValue = TRgb::Gray256((*alphaBuffer)[srcPixel.iX]);
+							}
+						drawDevice->WriteRgb(sourceDestXCoords.iY,yCoord.iY,maskRgbValue,drawMode);
+						spaceLeft--;
+						}
+					prevSourceDestXCoords = sourceDestXCoords;
+					xLine.SingleStep(sourceDestXCoords);
+					} while (spaceLeft > 0);
+				}
+			else
+				{
+				// No need to tile the mask
+				aMaskBitmap->StretchScanLine(scanLineDes,TPoint(maskXStart,yCoord.iX % maskHeight),
+										clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
+										srceWidth, KZeroPoint ,dispMode,aMaskBase,lineScanPosMask);
+				drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode);
+				// Redo stretching of the aSourceBitmap scanline
+				aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
+									 	clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
+									 	srceWidth, KZeroPoint ,dispMode,aSourceBase,lineScanPos2);
+				}
+
+			if (yCoord.iY==clippedDestRect.iTl.iY)
+				{
+				aSourceBitmap->SetCompressionBookmark(lineScanPos2,aSourceBase,NULL);
+				aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL);
+				}
+
+			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
+			}
+		yLine.NextStep(yCoord);
+		}
+	}
+
+TInt CSwDirectGdiEngine::FastBlendInterface(const CBitwiseBitmap* aSource, const CBitwiseBitmap* aMask, MFastBlend*& aFastBlend) const
+	{
+	#if defined(__ALLOW_FAST_BLEND_DISABLE__)
+	if (iFastBlendDisabled)
+		return(KErrNotSupported);
+	#endif
+	if ((aSource && aSource->IsCompressed()) || (aMask && aMask->IsCompressed()))
+		return(KErrNotSupported);
+	TAny* interface=NULL;
+	TInt ret= iDrawDevice->GetInterface(KFastBlendInterfaceID, interface);
+	aFastBlend=(MFastBlend*)interface;
+	return(ret);
+	}
+
+/*
+Returns the pixel-format to be used when extracting a scan-line through CBitwiseBitmap::GetScanLine(), CBitwiseBitmap::GetVerticalScanLine(), and CBitwiseBitmap::StretchScanLine() for consumption by CFbsDrawDevice::WriteLine() and associated methods.
+
+@see CBitwiseBitmap::GetScanLine()
+@see CBitwiseBitmap::GetVerticalScanLine()
+@see CBitwiseBitmap::StretchScanLine()
+@see CFbsDrawDevice::WriteLine()
+@internalComponent
+*/
+TDisplayMode CSwDirectGdiEngine::ScanLineBufferDisplayMode(CFbsDrawDevice* aDrawDevice)
+	{
+	return iDrawMode == DirectGdi::EDrawModeWriteAlpha ? aDrawDevice->DisplayMode() : aDrawDevice->ScanLineDisplayMode();
+	}