patch for Bug 1863 - CEikCba::SetBoundingRect() calls deprecated RWindowBase::SetShape()
// 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