--- /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
+