Fix def files so that the implementation agnostic interface definition has no non-standards defined entry points, and change the eglrefimpl specific implementation to place its private entry points high up in the ordinal order space in the implementation region, not the standards based entrypoints region.
// 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