graphicsdeviceinterface/screendriver/sbit/BMDRAW.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/screendriver/sbit/BMDRAW.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1652 @@
+// Copyright (c) 1997-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 "BMDRAW.H"
+#include "BitDrawInterfaceId.h"
+
+GLDEF_C void Panic(TScreenDriverPanic aPanicCode)
+	{
+	_LIT(KSCDVPanicCategory,"SCDV");
+	User::Panic(KSCDVPanicCategory,aPanicCode);
+	}
+
+
+/**
+Alphablends a pixel.
+The formula used for that, is:
+(aPrimary * aAlphaValue + aSecondary * (255 - aAlphaValue)) / 255 - for each color (R,G,B).
+@param aPrimary RGB color 1.
+@param aSecondary RGB color 2.
+@param aAlphaValue Mask.
+@return Alpha blended value.
+@internalComponent
+*/
+TRgb AlphaBlend(TRgb aPrimary, TRgb aSecondary, TInt aAlphaValue)
+    {
+    return ::AlphaBlend(aPrimary.Red(), aPrimary.Green(), aPrimary.Blue(), aSecondary, aAlphaValue);
+    }
+
+GLREF_D const TUint8 ditherlutab[16][4];
+
+const TInt8 xIncArray[4] = { 1, 0, -1, 0 };
+const TInt8 yIncArray[4] = { 0, 1, 0, -1 };
+
+static CFbsDrawDevice* CreateBitmapDeviceL(const TSize& aSize, TDisplayMode aDispMode, TInt aDataStride)
+	{
+	CFbsDrawDevice* drawDevice = NULL;
+
+	switch(aDispMode)
+		{
+	case EGray2:
+		drawDevice = new(ELeave) CDrawOneBppBitmap;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawOneBppBitmap*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EGray4:
+		drawDevice = new(ELeave) CDrawTwoBppBitmap;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawTwoBppBitmap*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EGray16:
+		drawDevice = new(ELeave) CDrawFourBppBitmapGray;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawFourBppBitmapGray*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EGray256:
+		drawDevice = new(ELeave) CDrawEightBppBitmapGray;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawEightBppBitmapGray*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EColor16:
+		drawDevice = new(ELeave) CDrawFourBppBitmapColor;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawFourBppBitmapColor*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EColor256:
+		drawDevice = new(ELeave) CDrawEightBppBitmapColor;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawEightBppBitmapColor*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EColor4K:
+		drawDevice = new(ELeave) CDrawTwelveBppBitmap;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawTwelveBppBitmap*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EColor64K:
+		drawDevice = new(ELeave) CDrawSixteenBppBitmap;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawSixteenBppBitmap*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EColor16M:
+		drawDevice = new(ELeave) CDrawTwentyFourBppBitmap;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawTwentyFourBppBitmap*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EColor16MU:
+		drawDevice = new(ELeave) CDrawUTwentyFourBppBitmap;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawUTwentyFourBppBitmap*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EColor16MA:
+		drawDevice = new(ELeave) CDrawThirtyTwoBppBitmapAlpha;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawThirtyTwoBppBitmapAlpha*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	case EColor16MAP:
+		drawDevice = new(ELeave) CDrawThirtyTwoBppBitmapAlphaPM;
+		CleanupStack::PushL(drawDevice);
+		User::LeaveIfError(((CDrawThirtyTwoBppBitmapAlphaPM*)drawDevice)->Construct(aSize, aDataStride));
+		break;
+	default:
+		Panic(EScreenDriverPanicInvalidDisplayMode);
+		}
+	CleanupStack::Pop(drawDevice); // drawDevice
+	return drawDevice;
+	}
+
+/**
+@deprecated Use NewBitmapDeviceL(const TSize& aSize, TDisplayMode aDispMode, TInt aDataStride)
+*/
+EXPORT_C CFbsDrawDevice* CFbsDrawDevice::NewBitmapDeviceL(TScreenInfoV01 aInfo,
+														  TDisplayMode aDispMode,
+														  TInt aDataStride)
+	{
+	return ::CreateBitmapDeviceL(aInfo.iScreenSize, aDispMode, aDataStride);
+	}
+
+/**
+Creates a new bitmap device instance, which implements CFbsDrawDevice interface.
+@param aSize Bitmap device size
+@param aDispMode Requested display mode
+@return A pointer to just created bitmap device, which implements CFbsDrawDevice interface
+@leave KErrNoMemory Not enough memory
+       KErrArgument Invalid aSize value
+*/
+EXPORT_C CFbsDrawDevice* CFbsDrawDevice::NewBitmapDeviceL(const TSize& aSize,
+														  TDisplayMode aDispMode,
+														  TInt aDataStride)
+	{
+	return ::CreateBitmapDeviceL(aSize, aDispMode, aDataStride);
+	}
+
+//Logical coordinates will be initialized with the right values, when SetSize() is called.
+CDrawBitmap::CDrawBitmap()
+	{
+	SetDefaults();
+	TInt err = GetInterface(KAlphaBlendInterfaceID, reinterpret_cast <TAny*&> (iAlphaBlend));
+    //There must be a support for an interface with KAlphaBlendInterfaceID id.
+    __ASSERT_ALWAYS(iAlphaBlend && err == KErrNone, User::Invariant());
+	}
+
+//Scanline width in pixels.
+//The return value can be greater or equal than iSize.iWidth, because
+//the scan line memory is allocated in 32-bit words and can be rounded up, if
+//the display mode allows more than 1 pixel to be stored in a single byte.
+TInt CDrawBitmap::LongWidth() const
+	{
+	//0 or 180 dgrees
+	if(!(iOrientation & 1))
+		{
+		return iLongWidth;
+		}
+	//90 or 270 degrees
+	return iSize.iWidth == 0 ? 0 : iLongWidth * iSize.iHeight / iSize.iWidth;
+	}
+
+TUint32* CDrawBitmap::ScanLineBuffer() const
+	{
+	return iScanLineBuffer;
+	}
+
+//Scanline width in bytes
+TInt CDrawBitmap::ScanLineBytes() const
+	{
+	register TInt scanLineBytes = iScanLineWords << 2;
+	//90 or 270 degrees
+	if(iOrientation & 1)
+		{
+		return iSize.iWidth == 0 ? 0 : scanLineBytes * iSize.iHeight / iSize.iWidth;
+		}
+	//0 or 180 degrees
+	return scanLineBytes;
+	}
+
+/**
+The method returns screen size in pixels. The orientation is taken into account.
+Always prefer GetDrawRect() to SizeInPixels() call.
+GetDrawRect() will take into account possible non-[0,0] top-left corner of the drawing
+rectangle if the device is scaled.
+@return TSize Screen size in pixels
+*/
+TSize CDrawBitmap::SizeInPixels() const
+	{
+	//90 or 270 degrees
+	if(iOrientation & 1)
+		{
+		return TSize(iDrawRect.Height(), iDrawRect.Width());
+		}
+	//0 or 180 degrees
+	return iDrawRect.Size();
+	}
+
+//aPoint - logical coordinates
+void CDrawBitmap::SetDitherOrigin(const TPoint& aPoint)
+	{
+	if (iOrientation&1)
+		{
+		iDitherOrigin.iX = ::Log2Phys(aPoint.iX,iOrigin.iX,iScalingSettings.iFactorY,iSize.iHeight);
+		iDitherOrigin.iY = ::Log2Phys(aPoint.iY,iOrigin.iY,iScalingSettings.iFactorX,iSize.iWidth);
+		}
+	else
+		{
+		iDitherOrigin.iX = ::Log2Phys(aPoint.iX,iOrigin.iX,iScalingSettings.iFactorX,iSize.iWidth);
+		iDitherOrigin.iY = ::Log2Phys(aPoint.iY,iOrigin.iY,iScalingSettings.iFactorY,iSize.iHeight);
+		}
+	}
+
+TInt CDrawBitmap::BitsPerPixel(TDisplayMode aDispMode)
+	{
+	switch(aDispMode)
+		{
+	case EGray2:
+		return 1;
+	case EGray4:
+		return 2;
+	case EGray16:
+	case EColor16:
+		return 4;
+	case EGray256:
+	case EColor256:
+		return 8;
+	case EColor4K:
+	case EColor64K:
+		return 16;
+	case EColor16M:
+		return 24;
+	case EColor16MU:
+	case EColor16MA:
+	case EColor16MAP:
+		return 32;
+	default:
+		return 0;
+		}
+	}
+
+void CDrawBitmap::OrientationsAvailable(TBool aOrientation[4])
+	{
+	aOrientation[EOrientationNormal] = ETrue;
+	aOrientation[EOrientationRotated90] = EFalse;
+	aOrientation[EOrientationRotated180] = EFalse;
+	aOrientation[EOrientationRotated270] = EFalse;
+	}
+
+//Works with logical coordinates
+void CDrawBitmap::Clear()
+	{
+	if(iBits)
+		{
+		if(iScalingOff && iOriginIsZero)
+			{
+			Mem::Fill(iBits, iScanLineWords * 4 * iSize.iHeight, 0xFF);
+			}
+		else
+			{
+			TShadowMode storedShadowMode = iShadowMode;
+			iShadowMode = ENoShadow;
+			TRect drawRect;
+			GetDrawRect(drawRect);
+			WriteRgbMulti(drawRect.iTl.iX, drawRect.iTl.iY, drawRect.Width(), drawRect.Height(), KRgbWhite, CGraphicsContext::EDrawModeWriteAlpha);
+			iShadowMode = storedShadowMode;
+			}
+		}
+	}
+
+CDrawBitmap::~CDrawBitmap()
+	{
+	if(iScanLineBuffer)
+		{
+		User::Free(iScanLineBuffer);
+		}
+	}
+
+//Works with logical sizes
+//The new device will accept old device scalling&scaling settings
+//All graphics contexts, already created by the scaled device, should be
+//re-activated calling CFbsBitGc::Activate().
+void CDrawBitmap::CopyOldSettings(CFbsDrawDevice* aDrawDevice)
+	{
+	__ASSERT_DEBUG(aDrawDevice, User::Invariant());
+	//Scaling&Origin settings - their values when scaling&origin are off.
+	const TPoint KDefaultOrigin(0, 0);
+	const TInt KDefaultFactorX = 1, KDefaultFactorY = 1;
+	const TInt KDefaultDivisorX = 1, KDefaultDivisorY = 1;
+	TPoint origin = KDefaultOrigin;//old device origin
+	TInt factorX = KDefaultFactorX, factorY = KDefaultFactorY;//old device - X and Y scaling factors
+	TInt divisorX = KDefaultDivisorX, divisorY = KDefaultDivisorY;//old device - X and Y scaling divisors
+	//Old device - set default scaling setings.
+	MScalingSettings* scalingSettings = NULL;
+	TInt err = aDrawDevice->GetInterface(KScalingSettingsInterfaceID, reinterpret_cast <TAny*&> (scalingSettings));
+	if(err == KErrNone)
+		{//There is a support for the interface with KScalingSettingsInterfaceID id.
+		__ASSERT_DEBUG(scalingSettings, User::Invariant());
+		scalingSettings->Get(factorX, factorY, divisorX, divisorY);
+		(void)scalingSettings->Set(KDefaultFactorX, KDefaultFactorY, KDefaultDivisorX, KDefaultDivisorY);
+		}
+	//Current device - set default scaling setings.
+	if(CanBeScaled())
+		{
+		(void)Set(KDefaultFactorX, KDefaultFactorY, KDefaultDivisorX, KDefaultDivisorY);
+		}
+	//Old device - set default origin.
+	MDrawDeviceOrigin* originInterface = NULL;
+	err = aDrawDevice->GetInterface(KDrawDeviceOriginInterfaceID, reinterpret_cast <TAny*&> (originInterface));
+	if(err == KErrNone)
+		{//There is a support for the interface with KDrawDeviceOriginInterfaceID id.
+		__ASSERT_DEBUG(originInterface, User::Invariant());
+		originInterface->Get(origin);
+		(void)originInterface->Set(KDefaultOrigin);
+		}
+	//Current device - set default origin.
+	if(CanOriginBeMoved())
+		{
+		(void)Set(KDefaultOrigin);
+		}
+	//Copy setigns
+	DoCopyOldSettings(aDrawDevice);
+	//Old device - restore scaling setings.
+	if(scalingSettings)
+		{
+		(void)scalingSettings->Set(factorX, factorY, divisorX, divisorY);
+		}
+	//Old device - restore origin.
+	if(originInterface)
+		{
+		(void)originInterface->Set(origin);
+		}
+	//Set current device scaling&origin settings to be the same as
+	//scaling&origin settings of the old device.
+	if(CanBeScaled())
+		{
+		(void)Set(factorX, factorY, divisorX, divisorY);
+		}
+	if(CanOriginBeMoved())
+		{
+		(void)Set(origin);
+		}
+	}
+
+void CDrawBitmap::DoCopyOldSettings(CFbsDrawDevice* aDrawDevice)
+	{
+	CDrawBitmap* oldDevice = (CDrawBitmap*)aDrawDevice;
+	iDitherOrigin = oldDevice->iDitherOrigin;
+	iShadowMode = oldDevice->iShadowMode;
+	SetOrientation(oldDevice->iOrientation);
+	iFadeMapFactor = oldDevice->iFadeMapFactor;
+	iFadeMapOffset = oldDevice->iFadeMapOffset;
+
+	TUint32* destRowPtr = iBits;
+	TUint32* destRowPtrLimit = iBits;
+	TInt destRowPtrInc = iScanLineWords;
+
+	TInt row = 0;
+	TInt rowInc = 1;
+
+	if (BitsPerPixel(oldDevice->iDispMode) < BitsPerPixel(iDispMode))
+		{
+		destRowPtr += (iSize.iHeight - 1) * iScanLineWords;
+		destRowPtrInc = -destRowPtrInc;
+		destRowPtrLimit -= iScanLineWords;
+		row = iSize.iHeight - 1;
+		rowInc = -1;
+		}
+	else
+		destRowPtrLimit += iSize.iHeight * iScanLineWords;
+
+	TOrientation oldOrientation=oldDevice->iOrientation;
+	oldDevice->SetOrientation(CFbsDrawDevice::EOrientationNormal);
+	while (destRowPtr != destRowPtrLimit)
+		{
+		aDrawDevice->ReadLine(0,row,iSize.iWidth,iScanLineBuffer,iDispMode);
+		Mem::Copy(destRowPtr,iScanLineBuffer,iScanLineWords << 2);
+		destRowPtr += destRowPtrInc;
+		row += rowInc;
+		}
+
+	oldDevice->SetOrientation(oldOrientation);
+	UpdateRegion(TRect(SizeInPixels()));
+	Update();
+	}
+
+TUint32 CDrawBitmap::Hash(TUint32 aGray16,TInt aX,TInt aY) const
+	{
+	if (iDitherOrigin.iX & 1)
+		aX++;
+	if (iDitherOrigin.iY & 1)
+		aY++;
+	aX &= 1;
+	aY &= 1;
+	return ditherlutab[aGray16][aX + (aY << 1)];
+	}
+
+//aRect - logical coordinates
+void CDrawBitmap::MapColors(const TRect& aRect, const TRgb* aColors,
+							TInt aNumPairs, TBool aMapForwards)
+	{
+	const TRect rect = DeOrientate(aRect);//deorientation and transformation of coordinates.
+	//rect - physical coordinates
+	__ASSERT_DEBUG(rect.iTl.iX >= 0 && rect.iBr.iX <= iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(rect.iTl.iY >= 0 && rect.iBr.iY <= iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aColors,Panic(EScreenDriverPanicNullPointer));
+	__ASSERT_DEBUG(aNumPairs > 0,Panic(EScreenDriverPanicZeroLength));
+
+	TRgb color;
+
+	TInt offset = aMapForwards ? 0 : 1;
+	TInt scaleX;
+	TInt scaleY;
+	if (iOrientation&1)
+		{
+		scaleX=iScalingSettings.iFactorY;
+		scaleY=iScalingSettings.iFactorX;
+		}
+	else
+		{
+		scaleX=iScalingSettings.iFactorX;
+		scaleY=iScalingSettings.iFactorY;
+		}
+	for(TInt ycoord = rect.iTl.iY; ycoord < rect.iBr.iY; ycoord+=scaleY)
+		{
+		for(TInt xcoord = rect.iTl.iX; xcoord < rect.iBr.iX; xcoord+=scaleX)
+			{
+			color = ReadRgbNormal(xcoord,ycoord);
+			for (TInt rgbcount = 0; rgbcount < aNumPairs; rgbcount++)
+				{
+				if (color == aColors[(rgbcount << 1) + offset])
+					{
+					WriteRgb(xcoord,ycoord,aColors[(rgbcount << 1) + 1 - offset]);
+					break;
+					}
+				}
+			}
+		}
+	}
+
+//form an int from the end portion of one and the start portion of another
+TUint32 CDrawBitmap::PasteInt(TUint32 aFirst,TUint32 aSecond,TInt aOffset) const
+	{
+	TUint32 mask=0;
+	if(aOffset<32) mask=0xffffffff>>aOffset;
+	aFirst&=mask;
+	aSecond&=~mask;
+	return(aFirst|aSecond);
+	}
+
+//returns the address of the start of scanline aY
+//aY- physical coordinate
+TUint32* CDrawBitmap::ScanLine(TInt aY) const
+	{
+	return iBits + (aY * iScanLineWords);
+	}
+
+void CDrawBitmap::SetBits(TAny* aBits)
+	{
+	iBits = STATIC_CAST(TUint32*,aBits);
+	}
+
+TBool CDrawBitmap::SetOrientation(TOrientation aOrientation)
+	{
+	if (iOrientation == aOrientation)
+		return ETrue;
+
+	return EFalse;
+	}
+
+void CDrawBitmap::SetFadingParameters(TUint8 aBlackMap,TUint8 aWhiteMap)
+	{
+	iFadeMapFactor = aWhiteMap - aBlackMap + 1;
+	iFadeMapOffset = aBlackMap;
+	}
+
+TRgb CDrawBitmap::FadeRgb(TRgb aColor)
+	{
+	TInt value = aColor.Internal();
+	TInt b = (((value & 0x000000ff) * iFadeMapFactor) >> 8)  + iFadeMapOffset;
+	TInt g = (((value & 0x0000ff00) * iFadeMapFactor) >> 16) + iFadeMapOffset;
+	//the multiplication by iFadeMapFactor can overflow into the sign bit, so we shift down in two steps
+	TInt r = ((((value & 0x00ff0000) >> 16) * iFadeMapFactor) >> 8) + iFadeMapOffset;
+	TInt a = aColor.Alpha();
+  	return TRgb(r,g,b,a);
+	}
+
+ TUint32 CDrawBitmap::FadeRgb(TUint32 aColor)
+  	{
+  	TInt value = aColor;
+
+  	TInt b = (((value & 0x000000ff) * iFadeMapFactor) >> 8)  + iFadeMapOffset;
+   	TInt g = (((value & 0x0000ff00) * iFadeMapFactor) >> 16) + iFadeMapOffset;
+  	//the multiplication by iFadeMapFactor can overflow into the sign bit, so we shift down in two steps
+   	TInt r = ((((value & 0x00ff0000) >> 16) * iFadeMapFactor) >> 8) + iFadeMapOffset;
+   	TInt a = aColor >> 24;
+   	return (a<<24) | ((r&0xff)<<16) | ((g&0xff)<<8) | (b&0xff);
+    }
+
+/**
+The overloaded function for FadeRgb(TRgb) which works directly with
+the Red, Green and Blue colour components to increase the performance.
+@param aRed Red component of colour.
+@param aGreen Green component of colour.
+@param aBlue Blue component of colour.
+*/
+void CDrawBitmap::FadeRgb(TInt& aRed, TInt& aGreen, TInt& aBlue)
+	{
+	aRed = ((aRed * iFadeMapFactor) >> 8)  + iFadeMapOffset;
+	aGreen = ((aGreen * iFadeMapFactor) >> 8)  + iFadeMapOffset;
+	aBlue = ((aBlue * iFadeMapFactor) >> 8)  + iFadeMapOffset;
+	}
+
+TUint8 CDrawBitmap::FadeGray(TInt aGray256)
+	{
+	return STATIC_CAST(TUint8,((aGray256 * iFadeMapFactor) >> 8) + iFadeMapOffset);
+	}
+
+//aX and aY - logical coordinates
+//aX and aY - deorientated and transformed to physical coordinates after the call
+void CDrawBitmap::DeOrientate(TInt& aX,TInt& aY) const
+	{
+	register TInt physWidth = iSize.iWidth;
+	register TInt physHeight = iSize.iHeight;
+	register TInt originX = iOrigin.iX;
+	register TInt originY = iOrigin.iY;
+	register TInt scalingFactorX = iScalingSettings.iFactorX;
+	register TInt scalingFactorY = iScalingSettings.iFactorY;
+	if(iOrientation & 0x1)
+		{
+		aX = ::Log2Phys(aX, originX, scalingFactorY, physHeight);
+		aY = ::Log2Phys(aY, originY, scalingFactorX, physWidth);
+		}
+	else
+		{
+		aX = ::Log2Phys(aX, originX, scalingFactorX, physWidth);
+		aY = ::Log2Phys(aY, originY, scalingFactorY, physHeight);
+		}
+
+	//aX and aY - descaled.
+	switch(iOrientation)
+		{
+		case EOrientationNormal:
+			{
+			return;
+			}
+		case EOrientationRotated180:
+			{
+			aX = physWidth - aX - 1;
+			aY = physHeight - aY - 1;
+			break;
+			}
+			case EOrientationRotated90:
+			{
+			TInt temp = physWidth - aY - 1;
+			aY = aX;
+			aX = temp;
+			break;
+			}
+		default: // EOrientationRotated270
+			{
+			TInt temp = aY;
+			aY = physHeight - aX - 1;
+			aX = temp;
+			}
+		}
+	}
+
+//aPoint - logical coordinates
+//The method returns TPoint object with deorientated and transformed to physical coordinates.
+TPoint CDrawBitmap::DeOrientate(const TPoint& aPoint) const
+	{
+	register TInt physWidth = iSize.iWidth;
+	register TInt physHeight = iSize.iHeight;
+	register TInt originX = iOrigin.iX;
+	register TInt originY = iOrigin.iY;
+	register TInt scalingFactorX = iScalingSettings.iFactorX;
+	register TInt scalingFactorY = iScalingSettings.iFactorY;
+	TPoint physPt;
+	if(iOrientation & 0x1)
+		{
+		physPt.iX = ::Log2Phys(aPoint.iX, originX, scalingFactorY, physHeight);
+		physPt.iY = ::Log2Phys(aPoint.iY, originY, scalingFactorX, physWidth);
+		}
+	else
+		{
+		physPt.iX = ::Log2Phys(aPoint.iX, originX, scalingFactorX, physWidth);
+		physPt.iY = ::Log2Phys(aPoint.iY, originY, scalingFactorY, physHeight);
+		}
+
+	//physPt - descaled
+	switch(iOrientation)
+		{
+		case EOrientationNormal:
+			{
+			return physPt;
+			}
+		case EOrientationRotated180:
+			{
+			return TPoint(physWidth - physPt.iX - 1, physHeight - physPt.iY - 1);
+			}
+		case EOrientationRotated90:
+			{
+			return TPoint(physWidth - physPt.iY - 1, physPt.iX);
+			}
+		// EOrientationRotated270
+		default:
+			return TPoint(physPt.iY, physHeight - physPt.iX - 1);
+		}
+	}
+
+//aRect - logical coordinates
+//The method returns TRect object with deorientated and transformed to physical coordinates.
+TRect CDrawBitmap::DeOrientate(const TRect& aRect) const
+	{
+	register TInt originX = iOrigin.iX;
+	register TInt originY = iOrigin.iY;
+	register TInt scalingFactorX = iScalingSettings.iFactorX;
+	register TInt scalingFactorY = iScalingSettings.iFactorY;
+	register TInt physWidth = iSize.iWidth;
+	register TInt physHeight = iSize.iHeight;
+	TRect physRect;
+	if(iOrientation & 0x1)
+		{
+		physRect.iTl.iX = ::Log2Phys(aRect.iTl.iX, originX, scalingFactorY, physHeight);
+		physRect.iTl.iY = ::Log2Phys(aRect.iTl.iY, originY, scalingFactorX, physWidth);
+		physRect.iBr.iX = ::RBtmLog2Phys(aRect.iBr.iX, originX, scalingFactorY, physHeight);
+		physRect.iBr.iY = ::RBtmLog2Phys(aRect.iBr.iY, originY, scalingFactorX, physWidth);
+		}
+	else
+		{
+		physRect.iTl.iX = ::Log2Phys(aRect.iTl.iX, originX, scalingFactorX, physWidth);
+		physRect.iTl.iY = ::Log2Phys(aRect.iTl.iY, originY, scalingFactorY, physHeight);
+		physRect.iBr.iX = ::RBtmLog2Phys(aRect.iBr.iX, originX, scalingFactorX, physWidth);
+		physRect.iBr.iY = ::RBtmLog2Phys(aRect.iBr.iY, originY, scalingFactorY, physHeight);
+		}
+
+	//physRect - descaled
+	if(iOrientation == EOrientationNormal)
+		{
+		return physRect;
+		}
+	if (iOrientation == EOrientationRotated180)
+		{
+		return TRect(TPoint(physWidth - physRect.iBr.iX, physHeight - physRect.iBr.iY), physRect.Size());
+		}
+	TSize altSize(physRect.Height(), physRect.Width());
+	TPoint altPoint;
+	if (iOrientation == EOrientationRotated90)
+		{
+		altPoint.SetXY(physWidth - physRect.iBr.iY, physRect.iTl.iX);
+		}
+	else // EOrientationRotated270
+		{
+		altPoint.SetXY(physRect.iTl.iY, physHeight - physRect.iBr.iX);
+		}
+	return TRect(altPoint, altSize);
+	}
+
+//aX and aY - logical coordinates
+TRgb CDrawBitmap::ReadPixel(TInt aX,TInt aY) const
+	{
+	DeOrientate(aX, aY);//aX and aY - physical coordinates
+
+	__ASSERT_DEBUG(aX >= 0 && aX < iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aY >= 0 && aY < iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
+
+	return ReadRgbNormal(aX, aY);
+	}
+
+//aX and aY - logical coordinates
+void CDrawBitmap::ReadLine(TInt aX,TInt aY,TInt aLength,
+						   TAny* aBuffer,TDisplayMode aDispMode) const
+	{
+	DeOrientate(aX,aY);//aX and aY - physical coordinates
+
+	__ASSERT_DEBUG(aX >= 0 && aX < iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aY >= 0 && aY < iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
+#if defined(_DEBUG)
+	switch (iOrientation)
+		{
+	case EOrientationNormal:
+		__ASSERT_DEBUG(aX + aLength <= iLongWidth,Panic(EScreenDriverPanicOutOfBounds));
+		break;
+	case EOrientationRotated90:
+		__ASSERT_DEBUG(aY + aLength <= iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
+		break;
+	case EOrientationRotated180:
+		__ASSERT_DEBUG(aX - aLength >= -1,Panic(EScreenDriverPanicOutOfBounds));
+		break;
+	default: // EOrientationRotated270
+		__ASSERT_DEBUG(aY - aLength >= -1,Panic(EScreenDriverPanicOutOfBounds));
+		break;
+		}
+#endif
+	__ASSERT_DEBUG(aLength > 0,Panic(EScreenDriverPanicZeroLength));
+	__ASSERT_DEBUG(aBuffer,Panic(EScreenDriverPanicNullPointer));
+
+	if (aDispMode == iDispMode)
+		{
+		ReadLine(aX,aY,aLength,aBuffer);
+		return;
+		}
+
+	TInt xInc = xIncArray[iOrientation];
+	TInt yInc = yIncArray[iOrientation];
+	if(iOrientation & 0x1)
+		{
+		xInc*=iScalingSettings.iFactorY;
+		yInc*=iScalingSettings.iFactorX;
+		}
+	else
+		{
+		xInc*=iScalingSettings.iFactorX;
+		yInc*=iScalingSettings.iFactorY;
+		}
+
+	switch (aDispMode)
+		{
+		case EGray2:
+			{
+			TUint8* bufferPtr = (TUint8*)aBuffer;
+
+			while (aLength >= 8)
+				{
+				bufferPtr[0] = TUint8(ReadRgbNormal(aX,aY)._Gray2());
+				aX += xInc; aY += yInc;
+				bufferPtr[0] |= TUint8(ReadRgbNormal(aX,aY)._Gray2() << 1);
+				aX += xInc; aY += yInc;
+				bufferPtr[0] |= TUint8(ReadRgbNormal(aX,aY)._Gray2() << 2);
+				aX += xInc; aY += yInc;
+				bufferPtr[0] |= TUint8(ReadRgbNormal(aX,aY)._Gray2() << 3);
+				aX += xInc; aY += yInc;
+				bufferPtr[0] |= TUint8(ReadRgbNormal(aX,aY)._Gray2() << 4);
+				aX += xInc; aY += yInc;
+				bufferPtr[0] |= TUint8(ReadRgbNormal(aX,aY)._Gray2() << 5);
+				aX += xInc; aY += yInc;
+				bufferPtr[0] |= TUint8(ReadRgbNormal(aX,aY)._Gray2() << 6);
+				aX += xInc; aY += yInc;
+				bufferPtr[0] |= TUint8(ReadRgbNormal(aX,aY)._Gray2() << 7);
+				aX += xInc; aY += yInc;
+				bufferPtr++;
+				aLength -= 8;
+				}
+			TInt bitShift = 0;
+			TInt bitLimit = aLength;
+			if (bitShift < bitLimit)
+				bufferPtr[0] = 0;
+			while (bitShift < bitLimit)
+				{
+				bufferPtr[0] |= TUint8(ReadRgbNormal(aX,aY)._Gray2() << bitShift);
+				aX += xInc; aY += yInc;
+				bitShift++;
+				}
+			}
+			break;
+		case EGray4:
+			{
+			TUint8* bufferPtr = REINTERPRET_CAST(TUint8*,aBuffer);
+
+			while (aLength > 3)
+				{
+				*bufferPtr = TUint8(ReadRgbNormal(aX,aY)._Gray4());
+				aX += xInc; aY += yInc;
+				*bufferPtr |= TUint8(ReadRgbNormal(aX,aY)._Gray4() << 2);
+				aX += xInc; aY += yInc;
+				*bufferPtr |= TUint8(ReadRgbNormal(aX,aY)._Gray4() << 4);
+				aX += xInc; aY += yInc;
+				*bufferPtr++ |= TUint8(ReadRgbNormal(aX,aY)._Gray4() << 6);
+				aX += xInc; aY += yInc;
+				aLength -= 4;
+				}
+			if (aLength > 0)
+				{
+				*bufferPtr = TUint8(ReadRgbNormal(aX,aY)._Gray4());
+				aX += xInc; aY += yInc;
+				aLength--;
+				}
+			if (aLength > 0)
+				{
+				*bufferPtr |= TUint8(ReadRgbNormal(aX,aY)._Gray4() << 2);
+				aX += xInc; aY += yInc;
+				aLength--;
+				}
+			if (aLength > 0)
+				*bufferPtr |= TUint8(ReadRgbNormal(aX,aY)._Gray4() << 4);
+			}
+			break;
+		case EGray16:
+			{
+			TUint8* bufferPtr = (TUint8*)aBuffer;
+
+			while (aLength > 1)
+				{
+				*bufferPtr = TUint8(ReadRgbNormal(aX,aY)._Gray16());
+				aX += xInc; aY += yInc;
+				*bufferPtr++ |= TUint8(ReadRgbNormal(aX,aY)._Gray16() << 4);
+				aX += xInc; aY += yInc;
+				aLength -= 2;
+				}
+			if (aLength > 0)
+				*bufferPtr = TUint8(ReadRgbNormal(aX,aY)._Gray16());
+			}
+			break;
+		case EGray256:
+			{
+			TUint8* bufferPtr = (TUint8*)aBuffer;
+			const TUint8* bufferPtrLimit = bufferPtr + aLength;
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				*bufferPtr++ = TUint8(ReadRgbNormal(aX,aY)._Gray256());
+				aX += xInc; aY += yInc;
+				}
+			}
+			break;
+		case EColor16:
+			{
+			TUint8* bufferPtr = (TUint8*)aBuffer;
+
+			while (aLength > 1)
+				{
+				*bufferPtr = TUint8(ReadRgbNormal(aX,aY).Color16());
+				aX += xInc; aY += yInc;
+				*bufferPtr++ |= TUint8(ReadRgbNormal(aX,aY).Color16() << 4);
+				aX += xInc; aY += yInc;
+				aLength -= 2;
+				}
+			if (aLength > 0)
+				*bufferPtr = TUint8(ReadRgbNormal(aX,aY).Color16());
+			}
+			break;
+		case EColor256:
+			{
+			TUint8* bufferPtr = (TUint8*)aBuffer;
+			const TUint8* bufferPtrLimit = bufferPtr + aLength;
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				*bufferPtr++ = TUint8(ReadRgbNormal(aX,aY).Color256());
+				aX += xInc; aY += yInc;
+				}
+			}
+			break;
+		case EColor4K:
+			{
+			TUint16* bufferPtr = (TUint16*)aBuffer;
+			const TUint16* bufferPtrLimit = bufferPtr + aLength;
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				*bufferPtr++ = TUint16(ReadRgbNormal(aX,aY)._Color4K());
+				aX += xInc; aY += yInc;
+				}
+			}
+			break;
+		case EColor64K:
+			{
+			TUint16* bufferPtr = (TUint16*)aBuffer;
+			const TUint16* bufferPtrLimit = bufferPtr + aLength;
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				*bufferPtr++ = TUint16(ReadRgbNormal(aX,aY)._Color64K());
+				aX += xInc; aY += yInc;
+				}
+			}
+			break;
+		case EColor16M:
+			{
+			TUint8* bufferPtr = (TUint8*)aBuffer;
+			const TUint8* bufferPtrLimit = bufferPtr + (aLength * 3);
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				TUint32 pixelColorValue = ReadRgbNormal(aX,aY).Internal();
+				aX += xInc; aY += yInc;
+				bufferPtr[0] = TUint8(pixelColorValue);
+				bufferPtr[1] = TUint8(pixelColorValue >> 8);
+				bufferPtr[2] = TUint8(pixelColorValue >> 16);
+				bufferPtr += 3;
+				}
+			}
+			break;
+		case ERgb:
+			{
+			TRgb* bufferPtr = (TRgb*)aBuffer;
+			const TRgb* bufferPtrLimit = bufferPtr + aLength;
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				*bufferPtr++ = ReadRgbNormal(aX,aY);
+				aX += xInc; aY += yInc;
+				}
+			}
+			break;
+		case EColor16MU:
+			{
+			TUint32* bufferPtr = (TUint32*)aBuffer;
+			const TUint32* bufferPtrLimit = bufferPtr + aLength;
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				*bufferPtr++ = ReadRgbNormal(aX,aY)._Color16MU();//BGRA (Blue/Green/Red/Alpha) as little endian bite order
+				aX += xInc; aY += yInc;
+				}
+			}
+			break;
+		case EColor16MA:
+			{
+			TUint32* bufferPtr = (TUint32*)aBuffer;
+			const TUint32* bufferPtrLimit = bufferPtr + aLength;
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				*bufferPtr++ = ReadRgbNormal(aX,aY)._Color16MA();//BGRA (Blue/Green/Red/Alpha) as little endian bite order
+				aX += xInc; aY += yInc;
+				}
+			}
+			break;
+		case EColor16MAP:
+			{
+			TUint32* bufferPtr = (TUint32*)aBuffer;
+			const TUint32* bufferPtrLimit = bufferPtr + aLength;
+
+			while (bufferPtr < bufferPtrLimit)
+				{
+				*bufferPtr++ = ReadRgbNormal(aX,aY)._Color16MAP();;
+				aX += xInc; aY += yInc;
+				}
+			}
+			break;
+		default:
+			Panic(EScreenDriverPanicInvalidDisplayMode);
+		}
+	}
+
+//aX, aY - logical coordinates
+void CDrawBitmap::WriteRgb(TInt aX,TInt aY,TRgb aColor,CGraphicsContext::TDrawMode aDrawMode)
+	{
+	register TInt width = -1;
+	register TInt height = -1;
+	PreWriteRgb(width, height, aX, aY, aDrawMode);
+	WriteRgb(width, height, aX, aY, aColor, aDrawMode);
+	}
+
+//aX, aY - logical coordinates
+void CDrawBitmap::WriteRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,
+								TRgb aColor,CGraphicsContext::TDrawMode aDrawMode)
+	{
+	const TRect rect = DeOrientate(TRect(aX,aY,aX + aLength,aY + aHeight));//rect - physical coordinates
+	aX = rect.iTl.iX;
+	aY = rect.iTl.iY;
+	aLength = rect.Width();
+	aHeight = rect.Height();
+
+	__ASSERT_DEBUG(aX>=0 && aX+aLength<=iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aY>=0 && aY+aHeight<=iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
+
+	MapColorToUserDisplayMode(aColor);
+	if(iShadowMode)
+		{
+		Shadow(aColor);
+		}
+	if(aDrawMode&CGraphicsContext::EInvertPen)
+		{
+		aColor=~aColor;
+		}
+	if(aDrawMode&CGraphicsContext::EPenmode)
+		{
+		BlendRgbMulti(aX,aY,aLength,aHeight,aColor);
+		return;
+		}
+	if(aDrawMode&CGraphicsContext::EWriteAlpha)
+		{
+		WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
+		return;
+		}
+	if(aDrawMode&CGraphicsContext::EInvertScreen)
+		{
+		WriteRgbMultiXOR(aX,aY,aLength,aHeight,KRgbWhite);
+		}
+	if(aDrawMode&CGraphicsContext::EXor)
+		{
+		WriteRgbMultiXOR(aX,aY,aLength,aHeight,aColor);
+		}
+	else if(aDrawMode&CGraphicsContext::EAnd)
+		{
+		WriteRgbMultiAND(aX,aY,aLength,aHeight,aColor);
+		}
+	else if(aDrawMode&CGraphicsContext::EOr)
+		{
+		WriteRgbMultiOR(aX,aY,aLength,aHeight,aColor);
+		}
+	}
+
+//aX, aY - logical coordinates
+void CDrawBitmap::WriteBinary(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,
+							  TInt aHeight,TRgb aColor,CGraphicsContext::TDrawMode aDrawMode)
+	{
+	TRect drawRect;
+	GetDrawRect(drawRect);
+	__ASSERT_DEBUG(aX >= drawRect.iTl.iX && (aX + aLength) <= drawRect.iBr.iX, Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aY >= drawRect.iTl.iY && (aY + aHeight) <= drawRect.iBr.iY, Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aBuffer, Panic(EScreenDriverPanicNullPointer));
+	__ASSERT_DEBUG(aLength > 0, Panic(EScreenDriverPanicZeroLength));
+	__ASSERT_DEBUG(aLength <= 32, Panic(EScreenDriverPanicOutOfBounds));
+
+	MapColorToUserDisplayMode(aColor);
+	if(iShadowMode)
+		Shadow(aColor);
+	if(aDrawMode&CGraphicsContext::EInvertPen)
+		aColor=~aColor;
+	if(aDrawMode&CGraphicsContext::EPenmode)
+		{
+		WriteBinary(aX,aY,aBuffer,aLength,aHeight,aColor);
+		return;
+		}
+	if(aDrawMode&CGraphicsContext::EInvertScreen)
+		WriteBinaryOp(aX,aY,aBuffer,aLength,aHeight,KRgbWhite,CGraphicsContext::EDrawModeXOR);
+	if(aDrawMode&CGraphicsContext::ELogicalOp)
+		WriteBinaryOp(aX,aY,aBuffer,aLength,aHeight,aColor,(CGraphicsContext::TDrawMode)(aDrawMode&CGraphicsContext::ELogicalOp));
+	}
+
+//aX, aY - logical coordinates
+void CDrawBitmap::WriteBinaryLine(TInt aX,TInt aY,TUint32* aBuffer,
+								  TInt aLength,TRgb aColor,
+								  CGraphicsContext::TDrawMode aDrawMode)
+	{
+	MapColorToUserDisplayMode(aColor);
+	while(aLength>32)
+		{
+		WriteBinary(aX,aY,aBuffer,32,1,aColor,aDrawMode);
+		aX+=32;
+		aBuffer++;
+		aLength-=32;
+		}
+	WriteBinary(aX,aY,aBuffer,aLength,1,aColor,aDrawMode);
+	}
+
+//aX, aY - logical coordinates
+void CDrawBitmap::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aBuffer,
+										  TInt aHeight,TRgb aColor,
+										  CGraphicsContext::TDrawMode aDrawMode,TBool aUp)
+	{
+	TRect drawRect;
+	GetDrawRect(drawRect);
+	__ASSERT_DEBUG(aX >= drawRect.iTl.iX && aX < drawRect.iBr.iX, Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aY >= drawRect.iTl.iY, Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aUp || (aY + aHeight) <= drawRect.iBr.iY, Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(!aUp || (aY - aHeight + 1) >= drawRect.iTl.iY, Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aBuffer, Panic(EScreenDriverPanicNullPointer));
+	__ASSERT_DEBUG(aHeight > 0, Panic(EScreenDriverPanicZeroLength));
+
+	MapColorToUserDisplayMode(aColor);
+	if((aDrawMode & CGraphicsContext::EPenmode) && iScalingOff)
+		{
+		if(iShadowMode)
+			Shadow(aColor);
+		if(aDrawMode&CGraphicsContext::EInvertPen)
+			aColor=~aColor;
+		WriteBinaryLineVertical(aX,aY,aBuffer,aHeight,aColor,aUp);
+		return;
+		}
+
+	TUint32 mask = 1;
+	TUint32 data = *aBuffer++;
+	TInt endrow = aY + (aUp ? -aHeight : aHeight);
+	TInt rowInc = aUp ? -1 : 1;
+
+	while (aY != endrow)
+		{
+		if (!mask)
+			{
+			data = *aBuffer++;
+			mask = 1;
+			}
+
+		if (data & mask)
+			{
+			WriteRgb(aX, aY, aColor, aDrawMode);
+			}
+
+		aY += rowInc;
+		mask <<= 1;
+		}
+	}
+
+//aX, aY - logical coordinates
+void CDrawBitmap::WriteLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer,
+							CGraphicsContext::TDrawMode aDrawMode)
+	{
+	const TPoint originalPoint(aX,aY);
+	DeOrientate(aX,aY);//aX and aY - physical coordinates
+
+	__ASSERT_DEBUG(aX >= 0,Panic(EScreenDriverPanicOutOfBounds));
+	__ASSERT_DEBUG(aY >= 0,Panic(EScreenDriverPanicOutOfBounds));
+#if defined(_DEBUG)
+	switch (iOrientation)
+		{
+	case EOrientationNormal:
+		__ASSERT_DEBUG(aX + aLength <= iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
+		break;
+	case EOrientationRotated90:
+		__ASSERT_DEBUG(aY + aLength <= iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
+		break;
+	case EOrientationRotated180:
+		__ASSERT_DEBUG(aX - aLength >= -1,Panic(EScreenDriverPanicOutOfBounds));
+		break;
+	default: // EOrientationRotated270
+		__ASSERT_DEBUG(aY - aLength >= -1,Panic(EScreenDriverPanicOutOfBounds));
+		break;
+		}
+#endif
+	__ASSERT_DEBUG(aLength > 0,Panic(EScreenDriverPanicZeroLength));
+	__ASSERT_DEBUG(aBuffer,Panic(EScreenDriverPanicNullPointer));
+
+	MapBufferToUserDisplayMode(aLength,aBuffer);
+	if(iShadowMode)
+		{
+		ShadowBuffer(aLength,aBuffer);
+		}
+	if(aDrawMode&CGraphicsContext::EInvertPen)
+		{
+		InvertBuffer(aLength,aBuffer);
+		}
+	if(aDrawMode&CGraphicsContext::EPenmode)
+		{
+		BlendLine(aX,aY,aLength,aBuffer);
+		return;
+		}
+	if(aDrawMode&CGraphicsContext::EWriteAlpha)
+		{
+		WriteLine(aX,aY,aLength,aBuffer);
+		return;
+		}
+	if(aDrawMode&CGraphicsContext::EInvertScreen)
+		{
+		const TRect rect = DeOrientate(TRect(originalPoint,TSize(aLength,1)));//"rect" - deorientated and scaled
+		WriteRgbMultiXOR(rect.iTl.iX,rect.iTl.iY,rect.Width(),rect.Height(),KRgbWhite);
+		}
+	if(aDrawMode&CGraphicsContext::EXor)
+		{
+		WriteLineXOR(aX,aY,aLength,aBuffer);
+		}
+	else if(aDrawMode&CGraphicsContext::EAnd)
+		{
+		WriteLineAND(aX,aY,aLength,aBuffer);
+		}
+	else if(aDrawMode&CGraphicsContext::EOr)
+		{
+		WriteLineOR(aX,aY,aLength,aBuffer);
+		}
+	}
+
+TAny* CDrawBitmap::CopyOffset(TAny* aDestination,const TAny* aSource,TInt aWordsToCopy,TInt aSourceBitOffset)
+	{
+	ASSERT(aSourceBitOffset > 0 && aSourceBitOffset < 32);
+
+	const TUint32* srcPtr = REINTERPRET_CAST(const TUint32*,aSource);
+	TUint32* destPtr = REINTERPRET_CAST(TUint32*,aDestination);
+	const TUint32* destPtrLimit = destPtr + aWordsToCopy;
+	const TInt sourceBitOffsetComplement = 32 - aSourceBitOffset;
+
+	TUint32 sourceValue = *srcPtr++;
+
+	while (destPtr < destPtrLimit)
+		{
+		TUint32 destValue = sourceValue >> aSourceBitOffset;
+		sourceValue = *srcPtr++;
+		destValue |= sourceValue << sourceBitOffsetComplement;
+		*destPtr++ = destValue;
+		}
+	return destPtr;
+	}
+/**	Common code to read a line of pixels where there are >1 pixels per byte.
+  	The source words must be shifted to fit the target buffer.
+@param 	aPixelPtr 	Source location to start copying from (word aligned, last word is safe)
+@param	aBufferPtr	Target location to write to (word aligned - may or may not own all last word)
+@param	aWordsCnt	Number of source words that can be safely copied
+@param	aRestPixels	Number of pixels that must be read from the next word for the final byte copy
+@param	aBytesCount	Number of bytes to write from final input word
+@param	aShiftBits	Number of bits shifted between input and output words.
+ **/
+void CDrawBitmap::ReadLineCommon(TUint32* aPixelPtr,TUint32* aBufferPtr,TInt aWordsCount,TInt aRestPixels,TInt aBytesCount,TInt aShiftBits)
+	{
+// 	As many pixels as possible are copied by shifting whole words.
+// 	This involves reading two source words, shifting them, 
+// 	and merging the result to one target word.
+//  	However, two cases mean the last few pixels need to be treated carefully:
+//  	1) The target buffer may be a number of bytes, not whole words.
+//			The number of pixels to copy defines the number of bytes to copy.
+//  	2) The number of pixels to read may mean the last read does not need 
+//  	   	to read a second word in order to satisfy the number of pixels requested.
+//  	   	This next word may not be mapped, so must not be read!
+
+	//Are we willing to pay for these asserts for every scanline copy, even in debug?
+	__ASSERT_DEBUG(aPixelPtr, User::Invariant());
+	__ASSERT_DEBUG(aBufferPtr, User::Invariant());
+	__ASSERT_DEBUG(aWordsCount>=0, User::Invariant());
+	__ASSERT_DEBUG(aBytesCount<5, User::Invariant());
+	__ASSERT_DEBUG(aShiftBits>=0 && aShiftBits<33, User::Invariant());
+	
+	TUint32 nextpixel;
+	if(aWordsCount>0)	
+		{
+		if (aShiftBits==0)
+			{
+			while (aWordsCount--)
+				{
+				*aBufferPtr++ = *aPixelPtr++;
+				}
+			if (aBytesCount>0)	//I hope the optimiser can concatenate these two tests?
+				{
+				nextpixel=aPixelPtr[0];
+				}
+			}
+		else
+			{
+			const TInt shiftBitsExtra = 32 - aShiftBits;
+			nextpixel=aPixelPtr[0]; 
+			while (aWordsCount--)
+				{
+				TUint32 prevpixel=nextpixel;
+				nextpixel=aPixelPtr[1];	//this must not read forward when it doesn't need to
+				aBufferPtr[0] = (prevpixel >> aShiftBits) | (nextpixel << shiftBitsExtra);
+
+				aPixelPtr++;
+				aBufferPtr++;
+				}
+			}
+		}
+	else
+		{
+		nextpixel=aPixelPtr[0];
+		}
+	
+	//deal with the trailing bytes
+	if (aBytesCount>0)
+		{
+		if (aBytesCount==4)
+			{
+			//The client only requests 4 bytes rather than 1 more word when the requested pixels
+			//mean the second word should not be read from.
+			//Can also write the result in a single operation!
+			aBufferPtr[0]=nextpixel>> aShiftBits;
+			}
+		else
+			{
+			if (aRestPixels>0)
+				{	
+				//do need to read from next word to fill all the requested pixels.
+				aWordsCount=(nextpixel >> aShiftBits) | (aPixelPtr[1] << (32 - aShiftBits));
+				}
+			else
+				{	
+				//Don't read second word, otherwise might read past end of picture data!
+				aWordsCount=(nextpixel >> aShiftBits);	
+				}
+			TUint8*	bufferPtrChar=reinterpret_cast <TUint8*> (aBufferPtr);
+
+			//max 3 bytes to store
+			if (aBytesCount&2)
+				{
+				bufferPtrChar[0]=aWordsCount;
+				bufferPtrChar[1]=aWordsCount>>8;
+				bufferPtrChar+=2;
+				aWordsCount>>=16;
+				}
+			if (aBytesCount&1)
+				{
+				bufferPtrChar[0]=aWordsCount;
+				}
+			}
+		}
+	}
+
+/**
+The method performs an alpha blending of the source data - aRgbBuffer and screen pixels, using
+the data from aMaskBuffer buffer as an alpha blending factor.
+If the shadowing/fading flag is set, a shadow/fade copy of the source bitmap will be used.
+The formula used for that, is:
+(C1 * A + C2 * (255 - A)) / 255, where:
+- C1 - a pixel from aRgbBuffer;
+- C2 - a pixel from the sceen;
+- A  - a pixel from aMaskBuffer;
+The content of source and mask buffers is preserved.
+The calculated alpha blended pixel is written to the destination - the screen or a bitmap.
+@param aX Logical X coordinate of the position in the target the result should be drawn to.
+@param aY Logical Y coordinate of the position in the target the result should be drawn to.
+@param aLength Source data - length in pixels.
+@param aRgbBuffer A pointer to a line of the source bitmap data.
+@param aMaskBuffer Buffer containing the data which should be used as an
+                   alpha blending factor.
+*/
+void CDrawBitmap::WriteRgbAlphaLine(TInt aX, TInt aY, TInt aLength,
+                                    TUint8* aRgbBuffer, TUint8* aMaskBuffer,
+                                    CGraphicsContext::TDrawMode aDrawMode)
+	{
+	iAlphaBlend->WriteRgbAlphaLine(aX, aY, aLength, aRgbBuffer, aMaskBuffer,
+                                   MAlphaBlend::EShdwBefore,
+                                   aDrawMode);
+	}
+
+/**
+The method performs an alpha blending of the source data - aRgbBuffer1 and aBuffer2, using
+the data from aMaskBuffer buffer as an alpha blending factor.
+If the shadowing/fading flag is set, the resulting pixels will be shadowed/faded.
+The formula used for that, is:
+(C1 * A + C2 * (255 - A)) / 255, where:
+- C1 - a pixel from aRgbBuffer1;
+- C2 - a pixel from aBuffer2;
+- A  - a pixel from aMaskBuffer;
+The content of source and mask buffers is preserved.
+The calculated alpha blended pixel is written to the destination - the screen or a bitmap.
+@param aX Logical X coordinate of the position in the target the result should be drawn to.
+@param aY Logical Y coordinate of the position in the target the result should be drawn to.
+@param aLength Source data - length in pixels.
+@param aRgbBuffer1 A pointer to a line of the source bitmap data 1.
+@param aBuffer2 A pointer to a line of the source bitmap data 2.
+                Source bitmap data 2 should be mapped to current display mode
+				before the method call.
+@param aMaskBuffer Buffer containing the data which should be used as an
+                   alpha blending factor.
+@param aDrawMode Drawing mode
+*/
+void CDrawBitmap::WriteRgbAlphaLine(TInt aX,TInt aY,TInt aLength,
+									const TUint8* aRgbBuffer1,
+									const TUint8* aBuffer2,
+									const TUint8* aMaskBuffer,
+									CGraphicsContext::TDrawMode aDrawMode)
+	{
+	// Save current shadow mode
+	TShadowMode temp_mode = iShadowMode;
+	iShadowMode = ENoShadow;
+	// copy the source data 2 to the screen/bitmap target buffer
+	WriteLine(aX, aY, aLength, (TUint32*)aBuffer2, aDrawMode);
+	// restore current shadow mode
+	iShadowMode = temp_mode;
+	// DrawModePen is the only supported operation for blending masks. 
+	iAlphaBlend->WriteRgbAlphaLine(aX, aY, aLength, aRgbBuffer1, aMaskBuffer,
+                                   MAlphaBlend::EShdwAfter, CGraphicsContext::EDrawModePEN);
+	}
+
+//Initializes iSize and iDrawRect data members.
+//It should be called every time when iSize is going to be changed - Construct() implementations
+//in derived classes.
+//The method does not use iOrientation data member.
+//@param aSize Physical screen size in pixels.
+//@panic EScreenDriverPanicInvalidSize - Invalid aSize parameter. This might happen if the
+//device is scaled and the scaling origin goes outside physical drawing rectangle.
+void CDrawBitmap::SetSize(const TSize& aSize)
+	{
+	iSize = aSize;
+	InitLogicalCoordinates();
+	}
+
+/**
+The method swaps bitmap device's width and height.
+For example: if the size is (40, 20), the swapped size will be (20, 40).
+The device's content is not preserved.
+The method leaves CDrawBitmap object in a consistent state -
+scaling settings will be set with their default values (the scaling is switched off),
+iDitherOrigin will be set to (0,0), iOrigin to (0,0).
+
+Note: This method is used internally by BITGDI component. Do not call it!
+*/
+void CDrawBitmap::SwapWidthAndHeight()
+	{
+	SetDefaults();
+	//Swap width and height
+	TSize swappedSize(iSize.iHeight, iSize.iWidth);
+	//Initialize iSize, iScanLineWords, iLongWidth data members.
+	SetSize(swappedSize);
+	}
+
+//This method initializes some of the data members.
+//Espetially it switches scaling off, sets iDitherOrigin to (0,0),
+//iOrigin to (0,0), iDrawRect to (0,0,0,0). iSize value is preserved.
+//Do not forget to update it if adding new data members!
+void CDrawBitmap::SetDefaults()
+	{
+	iLongWidth = 0;
+	iDitherOrigin.SetXY(0, 0);
+	iFadeMapFactor = 128;
+	iFadeMapOffset = 128;
+	iScalingSettings = TScalingSettings();
+	iOrigin.SetXY(0, 0);
+	iScalingOff = ETrue;
+	iOriginIsZero = ETrue;
+	iDrawRect.SetRect(0, 0, 0, 0);
+	}
+
+/**
+Implementation for CFbsDrawDevice::GetInterface().
+Retrieves a pointer to a specified interface of CFbsDrawDevice implementation.
+@param aInterfaceId Interface identifier of the interface to be retrieved.
+@param aInterface Address of variable that retrieves the specified interface.
+@return KErrNone If the interface is supported, KErrNotSupported otherwise.
+*/
+TInt CDrawBitmap::GetInterface(TInt aInterfaceId, TAny*& aInterface)
+	{
+	aInterface = NULL;
+	TInt err = KErrNotSupported;
+
+	switch (aInterfaceId)
+		{
+		case KScalingSettingsInterfaceID:
+			{
+			if(CanBeScaled())
+				{
+				aInterface = static_cast <MScalingSettings*> (this);
+				err = KErrNone;
+				}
+			break;
+			}
+		case KDrawDeviceOriginInterfaceID:
+			{
+			if(CanOriginBeMoved())
+				{
+				aInterface = static_cast <MDrawDeviceOrigin*> (this);
+				err = KErrNone;
+				}
+			break;
+			}
+		case KAlphaBlendInterfaceID:
+			{
+			aInterface = static_cast <MAlphaBlend*> (this);
+			err = KErrNone;
+			break;
+			}
+		case KOrientationInterfaceID:
+			{
+			aInterface = static_cast <MDrawDeviceOrientation*> (this);
+			err = KErrNone;    		
+			break;
+			}
+		case KOutlineAndShadowInterfaceID:
+			{
+			aInterface = static_cast <MOutlineAndShadowBlend*> (this);
+			err = KErrNone;    		
+			break;
+			}
+		case KFastBlendInterfaceID:
+			{
+			aInterface = static_cast <MFastBlend*> (this);
+			err = KErrNone;
+			break;
+			}
+		}
+	
+	return err;
+	}
+
+void CDrawBitmap::BlendRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
+	{
+	WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
+	}
+
+void CDrawBitmap::BlendLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
+	{
+	WriteLine(aX, aY,aLength, aBuffer);
+	}
+
+/**
+Convert a RGB pixel into the color associated to the user display mode.
+@param aRed red color
+@param aGreen green color
+@param aBlue blue color
+@internalComponent
+*/
+void CDrawBitmap::MapColorToUserDisplayMode(TInt& aRed,TInt& aGreen,TInt& aBlue)
+	{
+	TUint32 tmpValue;
+		
+	switch (iUserDispMode)
+		{
+		case EGray2:
+			tmpValue = ((aRed<<1) + aGreen + (aGreen<<2) + aBlue) >> 10;
+			if (tmpValue) 	{ aRed = 0xff; aBlue = 0xff; aGreen = 0xff; }
+			else			{ aRed = 0x00; aBlue = 0x00; aGreen = 0x00; }
+			break;
+		case EGray4:
+			tmpValue = ((aRed<<1) + aGreen + (aGreen<<2) + aBlue) >> 9;
+			tmpValue = tmpValue | (tmpValue << 2) | (tmpValue << 4) | (tmpValue << 6);
+			aRed = tmpValue; aGreen = tmpValue; aBlue = tmpValue;
+			break;
+		case EGray16:
+			tmpValue = ((aRed<<1) + aGreen + (aGreen<<2) + aBlue) >> 7;
+			tmpValue = tmpValue | (tmpValue << 4);
+			aRed = tmpValue; aGreen = tmpValue; aBlue = tmpValue;
+			break;
+	  	case EGray256:
+			tmpValue = ((aRed<<1) + aGreen + (aGreen<<2) + aBlue) >> 3;
+	  		aRed = tmpValue; aGreen = tmpValue; aBlue = tmpValue;
+	  		break;
+	  	case EColor16:
+	  		{
+	  		TRgb aColor(aRed,aGreen,aBlue);
+	  		aColor = TRgb::Color16(aColor.Color16());
+	  		aRed = aColor.Red(); aGreen = aColor.Green(); aBlue = aColor.Blue();
+	  		break;  		
+	  		}
+	  	case EColor256:
+	  		{
+	  		TRgb aColor2(aRed,aGreen,aBlue);
+	  		aColor2 = TRgb::Color256(aColor2.Color256());
+	  		aRed = aColor2.Red(); aGreen = aColor2.Green(); aBlue = aColor2.Blue();
+	  		break;
+	  		}
+	  	case EColor4K:
+	  		aBlue = aBlue  & 0xf0; 	aBlue |= (aBlue >> 4);
+	  		aGreen = aGreen  & 0xf0;	aGreen |= (aGreen >> 4);
+	  		aRed = aRed  & 0xf0; 		aRed |= (aRed >> 4);
+	  		break;
+	  	case EColor64K:
+	  		aBlue = aBlue  & 0xf8;	aBlue += (aBlue >> 5);
+	  		aGreen = aGreen  & 0xfc;	aGreen += (aGreen >> 6);
+	  		aRed = aRed  & 0xf8;		aRed += (aRed >> 5);
+	  		break;
+	  	default:
+	  		break;
+  		}
+	}
+
+/**
+CDrawBitmap::Orientation() implementation.
+@internalTechnology
+@see MDrawDeviceOrientation::Orientation()
+*/
+CFbsDrawDevice::TOrientation CDrawBitmap::Orientation()
+	{
+	return iOrientation;
+	}
+
+#ifdef __ARMCC__
+#ifndef __MARM_THUMB__
+#define USE_SCREENDRIVER_ARM_ASM
+#endif //__MARM_THUMB__
+#endif //__ARMCC__
+
+#ifdef USE_SCREENDRIVER_ARM_ASM
+/**
+MemFill - using an unrolled loop to perform the following:
+	for (TUint32* tempWordPtr = wordPtr; tempWordPtr < wordPtrLimit; tempWordPtr++)
+		{
+		*tempWordPtr = colorWord;
+		}
+*/
+__asm void MemFillTUint32(TUint32* /*aTrg*/, TInt /*aLength*/, const TUint32 /*aValue*/)
+	{
+	//r0 - aTrg, r1 - aLength, r2 - aValue
+	push     {r1,r3,lr}
+	and      r3,r1,#7
+	cmp      r3,#7
+	addls    pc,pc,r3,LSL #2
+	b        mf_switch0
+	b        mf_switch0
+	b        mf_switch1
+	b        mf_switch2
+	b        mf_switch3
+	b        mf_switch4
+	b        mf_switch5
+	b        mf_switch6
+	b        mf_switch7
+mf_switch7
+	str      r2,[r0],#4
+mf_switch6
+	str      r2,[r0],#4
+mf_switch5
+	str      r2,[r0],#4
+mf_switch4
+	str      r2,[r0],#4
+mf_switch3
+	str      r2,[r0],#4
+mf_switch2
+	str      r2,[r0],#4
+mf_switch1
+	str      r2,[r0],#4
+mf_switch0
+
+	asr      r1,r1,#3
+	cmp      r1,#0
+	beq      mf_complete
+
+	push     {r0,r2,r4-r8}
+	mov      r3,r2
+	mov      r4,r2
+    mov      r5,r2
+    mov      r6,r2
+	mov      r7,r2
+	mov      r8,r2
+	mov      lr,r2
+
+mf_more
+	stmia    r0!,{r2-r8,lr}
+	subs     r1,r1,#1
+	bgt      mf_more
+	pop     {r0,r2,r4-r8}
+
+mf_complete
+	pop     {r1,r3,pc}
+	}
+
+#else //USE_SCREENDRIVER_ARM_ASM
+
+const TInt KDevideByEightShift = 3;
+const TInt KModulusByEightFlag = 7;
+
+void MemFillTUint32(TUint32* tempWordPtr, TInt aCount,  const TUint32 aValue)
+	{
+	TInt remainder = aCount & KModulusByEightFlag;
+	switch (remainder)
+		{
+	case 7:
+		*tempWordPtr++ = aValue;
+	case 6:
+		*tempWordPtr++ = aValue;
+	case 5:
+		*tempWordPtr++ = aValue;
+	case 4:
+		*tempWordPtr++ = aValue;
+	case 3:
+		*tempWordPtr++ = aValue;
+	case 2:
+		*tempWordPtr++ = aValue;
+	case 1:
+		*tempWordPtr++ = aValue;
+		}
+	register TUint32 value0 = aValue;
+	register TUint32 value1 = aValue;
+	register TUint32 value2 = aValue;
+	for(TInt times = (aCount >> KDevideByEightShift); times > 0; --times)
+		{
+		*tempWordPtr++ = value0;
+		*tempWordPtr++ = value1;
+		*tempWordPtr++ = value2;
+		*tempWordPtr++ = aValue;
+		*tempWordPtr++ = value0;
+		*tempWordPtr++ = value1;
+		*tempWordPtr++ = value2;
+		*tempWordPtr++ = aValue;
+		}
+	}
+
+#endif //USE_SCREENDRIVER_ARM_ASM
+