diff -r 000000000000 -r 5d03bc08d59c graphicsdeviceinterface/screendriver/sbit/BMDRAW.CPP --- /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 (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 (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 (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 (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 (this); + err = KErrNone; + } + break; + } + case KDrawDeviceOriginInterfaceID: + { + if(CanOriginBeMoved()) + { + aInterface = static_cast (this); + err = KErrNone; + } + break; + } + case KAlphaBlendInterfaceID: + { + aInterface = static_cast (this); + err = KErrNone; + break; + } + case KOrientationInterfaceID: + { + aInterface = static_cast (this); + err = KErrNone; + break; + } + case KOutlineAndShadowInterfaceID: + { + aInterface = static_cast (this); + err = KErrNone; + break; + } + case KFastBlendInterfaceID: + { + aInterface = static_cast (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 +