// 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"
//Initializes iSize, iDrawRect, iLongWidth, iScanLineBytes, iScanlineWords data members.
//It should be called every time when iSize is going to be changed - from Construct().
//@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 CDrawTwentyFourBppBitmap::SetSize(const TSize& aSize)
{
CDrawBitmap::SetSize(aSize);
__ASSERT_DEBUG(iSize == aSize, User::Invariant());
iScanLineBytes = (((iSize.iWidth * 3) + 11) / 12) * 12;
iLongWidth = iScanLineBytes / 3;
iScanLineWords = iScanLineBytes / 4;
}
TInt CDrawTwentyFourBppBitmap::Construct(TSize aSize)
{
return Construct(aSize, (((aSize.iWidth * 3) + 11) / 12) * 12);
}
TInt CDrawTwentyFourBppBitmap::Construct(TSize aSize, TInt aStride)
{
iBits = NULL;
iDispMode = EColor16M;
CDrawBitmap::SetSize(aSize);
__ASSERT_DEBUG(iSize == aSize, User::Invariant());
if (aStride % 12)
return KErrArgument;
iScanLineBytes = aStride;
iLongWidth = aStride / 3;
if (iLongWidth < aSize.iWidth)
return KErrArgument;
iScanLineWords = aStride >> 2;
TInt size = (((Max(aSize.iWidth,aSize.iHeight) * 3) + 11) / 12) * 12;
if(size < 0)
return KErrArgument;
iScanLineBuffer = (TUint32*)(User::Heap().Alloc(size));
if (iScanLineBuffer == NULL)
return KErrNoMemory;
return KErrNone;
}
inline TInt CDrawTwentyFourBppBitmap::PixelAddressIncrement() const
{
switch (iOrientation)
{
case EOrientationNormal:
return 3;
case EOrientationRotated90:
return iScanLineBytes;
case EOrientationRotated180:
return -3;
case EOrientationRotated270:
return -iScanLineBytes;
default:
return 1;
}
}
inline void CDrawTwentyFourBppBitmap::PixelAddressIncrement(TInt& aPixelInc,TInt& aRowInc) const
{
switch (iOrientation)
{
case EOrientationNormal:
aPixelInc = 3;
aRowInc = iScanLineBytes;
break;
case EOrientationRotated90:
aPixelInc = iScanLineBytes;
aRowInc = -3;
break;
case EOrientationRotated180:
aPixelInc = -3;
aRowInc = -iScanLineBytes;
break;
case EOrientationRotated270:
aPixelInc = -iScanLineBytes;
aRowInc = 3;
break;
default:
aPixelInc = 1;
aRowInc = 1;
}
}
void CDrawTwentyFourBppBitmap::FadeRgb(TInt& red,TInt& green,TInt& blue)
{
blue = ((blue * iFadeMapFactor) >> 8) + iFadeMapOffset;
green = ((green * iFadeMapFactor) >> 16) + iFadeMapOffset;
red = ((red * iFadeMapFactor) >> 8) + iFadeMapOffset;
}
void CDrawTwentyFourBppBitmap::Shadow(TRgb& aColor)
{
if (iShadowMode & EFade)
aColor = CDrawBitmap::FadeRgb(aColor);
if (iShadowMode & EShadow)
{
TInt r = ShadowComponentInl(aColor.Red());
TInt g = ShadowComponentInl(aColor.Green());
TInt b = ShadowComponentInl(aColor.Blue());
aColor = TRgb(r,g,b);
}
}
void CDrawTwentyFourBppBitmap::Shadow(TInt& red,TInt& green,TInt& blue)
{
if (iShadowMode & EFade)
FadeRgb(red,green,blue);
if (iShadowMode & EShadow)
{
red = ShadowComponentInl(red);
green = ShadowComponentInl(green);
blue = ShadowComponentInl(blue);
}
}
TUint8 CDrawTwentyFourBppBitmap::ShadowAndFade(TInt aComponent)
{
if (iShadowMode & EFade)
aComponent = FadeGray(aComponent);
if (iShadowMode & EShadow)
aComponent = ShadowComponentInl(aComponent);
return TUint8(aComponent);
}
TUint8 CDrawTwentyFourBppBitmap::ShadowComponentInl(TInt aRgbComponent)
{
return TUint8(Max(0,aRgbComponent-0x40));
}
TUint8 CDrawTwentyFourBppBitmap::ShadowComponent(TInt aRgbComponent)
{
return ShadowComponentInl(aRgbComponent);
}
void CDrawTwentyFourBppBitmap::InvertBuffer(TInt aLength,TUint32* aBuffer)
{
__ASSERT_DEBUG(aLength>0,Panic(EScreenDriverPanicOutOfBounds));
__ASSERT_DEBUG(aBuffer,Panic(EScreenDriverPanicNullPointer));
TUint8* buffer = (TUint8*)aBuffer;
TUint8* limit = buffer + (aLength * 3);
while (buffer < limit)
*buffer++ ^= 0xff;
}
void CDrawTwentyFourBppBitmap::ReadLine(TInt aX,TInt aY,TInt aLength,TAny* aBuffer) const
{
const TUint8* pixelPtr = PixelAddress(aX,aY);
if (iOrientation == EOrientationNormal)
Mem::Copy(aBuffer,pixelPtr,aLength * 3);
else
{
const TInt pixelPtrInc = PixelAddressIncrement();
TUint8* bufferPtr = STATIC_CAST(TUint8*,aBuffer);
const TUint8* bufferPtrLimit = bufferPtr + (aLength * 3);
while (bufferPtr < bufferPtrLimit)
{
*bufferPtr++ = pixelPtr[0];
*bufferPtr++ = pixelPtr[1];
*bufferPtr++ = pixelPtr[2];
pixelPtr += pixelPtrInc;
}
}
}
TRgb CDrawTwentyFourBppBitmap::ReadRgbNormal(TInt aX,TInt aY) const
{
TUint8* pixelPtr = PixelAddress(aX,aY);
return TRgb(pixelPtr[2],pixelPtr[1],pixelPtr[0]);
}
void CDrawTwentyFourBppBitmap::ShadowArea(const TRect& aRect)
{
const TRect rect(DeOrientate(aRect));
__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));
TUint8* pixelPtr = PixelAddress(rect.iTl.iX,rect.iTl.iY);
TUint8* pixelRowPtrLimit = pixelPtr + (rect.Height() * iScanLineBytes);
if (iShadowMode & EFade)
{
TUint8* pixelRowPtr = pixelPtr;
TUint8* pixelPtrLimit = pixelPtr + (rect.Width() * 3);
while (pixelRowPtr < pixelRowPtrLimit)
{
TUint8* tempPixelPtr = pixelRowPtr;
while (tempPixelPtr < pixelPtrLimit)
{
*tempPixelPtr = FadeGray(*tempPixelPtr);
++tempPixelPtr;
}
pixelRowPtr += iScanLineBytes;
pixelPtrLimit += iScanLineBytes;
}
}
if (iShadowMode & EShadow)
{
TUint8* pixelRowPtr = pixelPtr;
TUint8* pixelPtrLimit = pixelPtr + (rect.Width() * 3);
while (pixelRowPtr < pixelRowPtrLimit)
{
TUint8* tempPixelPtr = pixelRowPtr;
while (tempPixelPtr < pixelPtrLimit)
{
*tempPixelPtr = ShadowComponent(*tempPixelPtr);
++tempPixelPtr;
}
pixelRowPtr += iScanLineBytes;
pixelPtrLimit += iScanLineBytes;
}
}
}
void CDrawTwentyFourBppBitmap::ShadowBuffer(TInt aLength,TUint32* aBuffer)
{
__ASSERT_DEBUG(aLength>0,Panic(EScreenDriverPanicZeroLength));
__ASSERT_DEBUG(aBuffer,Panic(EScreenDriverPanicNullPointer));
TUint8* limit = ((TUint8*)aBuffer) + (aLength * 3);
if (iShadowMode & EFade)
{
TUint8* buffer = (TUint8*)aBuffer;
while (buffer < limit)
{
*buffer = FadeGray(*buffer);
++buffer;
}
}
if (iShadowMode & EShadow)
{
TUint8* buffer = (TUint8*)aBuffer;
while (buffer < limit)
{
*buffer = ShadowComponent(*buffer);
++buffer;
}
}
}
void CDrawTwentyFourBppBitmap::WriteRgb(TInt aX,TInt aY,TRgb aColor)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
pixelPtr[0] = TUint8(aColor.Blue());
pixelPtr[1] = TUint8(aColor.Green());
pixelPtr[2] = TUint8(aColor.Red());
}
void CDrawTwentyFourBppBitmap::WriteBinary(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,TInt aHeight,TRgb aColor)
{
DeOrientate(aX,aY);
TInt pixelInc;
TInt rowInc;
PixelAddressIncrement(pixelInc,rowInc);
const TUint32* dataLimit = aBuffer + aHeight;
const TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
TUint8* pixelPtr = PixelAddress(aX,aY);
const TUint8 r = (TUint8)aColor.Red();
const TUint8 g = (TUint8)aColor.Green();
const TUint8 b = (TUint8)aColor.Blue();
while (aBuffer < dataLimit)
{
TUint32 dataWord = *aBuffer++;
TUint32 dataMask = 1;
TUint8* tempPixelPtr = pixelPtr;
while (dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
tempPixelPtr[0] = b;
tempPixelPtr[1] = g;
tempPixelPtr[2] = r;
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
}
pixelPtr += rowInc;
}
}
void CDrawTwentyFourBppBitmap::WriteBinaryOp(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,TInt aHeight,TRgb aColor,CGraphicsContext::TDrawMode aDrawMode)
{
if (aLength <= 0)
return;
DeOrientate(aX,aY);
TUint8* pixelPtr = PixelAddress(aX,aY);
const TUint32* dataPtrLimit = aBuffer + aHeight;
const TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
TInt pixelInc;
TInt rowInc;
PixelAddressIncrement(pixelInc,rowInc);
const TUint8 r = (TUint8)aColor.Red();
const TUint8 g = (TUint8)aColor.Green();
const TUint8 b = (TUint8)aColor.Blue();
if (r || g || b)
{
while (aBuffer < dataPtrLimit)
{
TUint32 dataWord = *aBuffer++;
TUint32 dataMask = 1;
TUint8* tempPixelPtr = pixelPtr;
while (dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
switch (aDrawMode)
{
case CGraphicsContext::EDrawModeXOR:
tempPixelPtr[0] ^= b;
tempPixelPtr[1] ^= g;
tempPixelPtr[2] ^= r;
break;
case CGraphicsContext::EDrawModeAND:
tempPixelPtr[0] &= b;
tempPixelPtr[1] &= g;
tempPixelPtr[2] &= r;
break;
case CGraphicsContext::EDrawModeOR:
tempPixelPtr[0] |= b;
tempPixelPtr[1] |= g;
tempPixelPtr[2] |= r;
break;
default:
break;
}
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
}
pixelPtr += rowInc;
}
}
else if (aDrawMode == CGraphicsContext::EDrawModeAND)
{
while (aBuffer < dataPtrLimit)
{
TUint32 dataWord = *aBuffer++;
TUint32 dataMask = 1;
TUint8* tempPixelPtr = pixelPtr;
while (dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
tempPixelPtr[0] = 0;
tempPixelPtr[1] = 0;
tempPixelPtr[2] = 0;
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
}
pixelPtr += rowInc;
}
}
}
void CDrawTwentyFourBppBitmap::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aBuffer,TInt aHeight,TRgb aColor,TBool aUp)
{
DeOrientate(aX,aY);
TInt scanlineByteLength;
switch (iOrientation)
{
case EOrientationNormal:
scanlineByteLength = iScanLineBytes;
break;
case EOrientationRotated90:
scanlineByteLength = -3;
break;
case EOrientationRotated180:
scanlineByteLength = -iScanLineBytes;
break;
default: // EOrientationRotated270
scanlineByteLength = 3;
break;
}
if (aUp)
scanlineByteLength = -scanlineByteLength;
TUint8* pixelPtr = PixelAddress(aX,aY);
const TUint8* pixelPtrLimit = pixelPtr + (aHeight * scanlineByteLength);
TUint32 dataWord = *aBuffer;
TUint32 dataMask = 1;
const TUint8 r = (TUint8)aColor.Red();
const TUint8 g = (TUint8)aColor.Green();
const TUint8 b = (TUint8)aColor.Blue();
while(pixelPtr != pixelPtrLimit)
{
if(!dataMask)
{
dataMask = 1;
aBuffer++;
dataWord = *aBuffer;
}
if(dataWord & dataMask)
{
pixelPtr[0] = b;
pixelPtr[1] = g;
pixelPtr[2] = r;
}
dataMask <<= 1;
pixelPtr += scanlineByteLength;
}
}
void CDrawTwentyFourBppBitmap::WriteLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
if (iOrientation == EOrientationNormal)
Mem::Copy(pixelPtr,aBuffer,aLength * 3);
else
{
const TInt pixelPtrInc = PixelAddressIncrement();
TUint8* bufferPtr = REINTERPRET_CAST(TUint8*,aBuffer);
TUint8* bufferPtrLimit = bufferPtr + (aLength * 3);
while (bufferPtr < bufferPtrLimit)
{
pixelPtr[0] = *bufferPtr++;
pixelPtr[1] = *bufferPtr++;
pixelPtr[2] = *bufferPtr++;
pixelPtr += pixelPtrInc;
}
}
}
void CDrawTwentyFourBppBitmap::WriteLineXOR(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
const TInt pixelPtrInc = PixelAddressIncrement();
TUint8* bufferPtr = REINTERPRET_CAST(TUint8*,aBuffer);
TUint8* bufferPtrLimit = bufferPtr + (aLength * 3);
while (bufferPtr < bufferPtrLimit)
{
pixelPtr[0] ^= *bufferPtr++;
pixelPtr[1] ^= *bufferPtr++;
pixelPtr[2] ^= *bufferPtr++;
pixelPtr += pixelPtrInc;
}
}
void CDrawTwentyFourBppBitmap::WriteLineAND(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
const TInt pixelPtrInc = PixelAddressIncrement();
TUint8* bufferPtr = REINTERPRET_CAST(TUint8*,aBuffer);
TUint8* bufferPtrLimit = bufferPtr + (aLength * 3);
while (bufferPtr < bufferPtrLimit)
{
pixelPtr[0] &= *bufferPtr++;
pixelPtr[1] &= *bufferPtr++;
pixelPtr[2] &= *bufferPtr++;
pixelPtr += pixelPtrInc;
}
}
void CDrawTwentyFourBppBitmap::WriteLineOR(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
const TInt pixelPtrInc = PixelAddressIncrement();
TUint8* bufferPtr = REINTERPRET_CAST(TUint8*,aBuffer);
TUint8* bufferPtrLimit = bufferPtr + (aLength * 3);
while (bufferPtr < bufferPtrLimit)
{
pixelPtr[0] |= *bufferPtr++;
pixelPtr[1] |= *bufferPtr++;
pixelPtr[2] |= *bufferPtr++;
pixelPtr += pixelPtrInc;
}
}
/**
MAlphaBlend::WriteRgbAlphaLine() implementation.
@see MAlphaBlend::WriteRgbAlphaLine()
*/
void CDrawTwentyFourBppBitmap::WriteRgbAlphaLine(TInt aX, TInt aY, TInt aLength,
const TUint8* aRgbBuffer,
const TUint8* aMaskBuffer,
MAlphaBlend::TShadowing aShadowing,
CGraphicsContext::TDrawMode /*aDrawMode*/)
{
DeOrientate(aX,aY);
TUint8* pixelPtr = PixelAddress(aX,aY);
const TInt pixelPtrInc = PixelAddressIncrement();
const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
while (aMaskBuffer < maskBufferPtrLimit)
{
TInt mask = aMaskBuffer[0];
if(mask)
{
TInt red = aRgbBuffer[2];
TInt green = aRgbBuffer[1];
TInt blue = aRgbBuffer[0];
if(aShadowing == MAlphaBlend::EShdwBefore)
{
Shadow(red,green,blue);
}
if(aMaskBuffer[0] != 0xff) // Blend 24bpp
{
mask = mask * 257;
red = (((red - pixelPtr[2]) * mask) >> 16) + pixelPtr[2];
green = (((green - pixelPtr[1]) * mask) >> 16) + pixelPtr[1];
blue = (((blue - pixelPtr[0]) * mask) >> 16) + pixelPtr[0];
}
if(aShadowing == MAlphaBlend::EShdwAfter)
{
Shadow(red,green,blue);
}
CDrawBitmap::MapColorToUserDisplayMode(red,green,blue);
pixelPtr[0] = TUint8(blue);
pixelPtr[1] = TUint8(green);
pixelPtr[2] = TUint8(red);
}
pixelPtr += pixelPtrInc;
aRgbBuffer += 4;
aMaskBuffer++;
}
}
const TUint32 KWordAlignedCount = 4;
const TUint32 KWordAlignedMask = 3;
const TUint32 KFinishEarlyByThree = 3;
void WriteTwentyFourBppColourAsWords(TUint8& r, TUint8& g, TUint8& b, TUint8* pixelPtr, const TInt byteLength, TUint8* pixelRowPtrLimit, const TInt scanLineBytes)
{
TUint8 bgr[3] =
{
b,g,r
};
TUint32 bgrb = b+(g<<8)+(r<<16)+(b<<24);
TUint32 grbg = g+(r<<8)+(b<<16)+(g<<24);
TUint32 rbgr = r+(b<<8)+(g<<16)+(r<<24);
TUint8* pixelPtrLimit = pixelPtr + byteLength;
TInt leadingPixels = KWordAlignedCount-((TUint32)pixelPtr)&KWordAlignedMask;
if (leadingPixels == KWordAlignedCount)
leadingPixels = 0;
const TInt trailingPixels = ((TUint32)pixelPtrLimit & KWordAlignedMask);
while (pixelPtr < pixelRowPtrLimit)
{
TUint8* tempPixelPtr;
TUint32* tempWordPtr;
TInt nextOfBgr = 0;
TUint8* leadingPixelPtrLimit = pixelPtr+leadingPixels;
for (tempPixelPtr = pixelPtr; tempPixelPtr < leadingPixelPtrLimit; tempPixelPtr++)
{
tempPixelPtr[0] = bgr[nextOfBgr++];
}
if (nextOfBgr == (KWordAlignedCount-1))
nextOfBgr = 0;
TUint32* wordPtrLimit = ((TUint32*)(pixelPtrLimit-trailingPixels))-KFinishEarlyByThree;
tempWordPtr = (TUint32*)tempPixelPtr;
switch (nextOfBgr)
{
case 1:
if (tempWordPtr < wordPtrLimit)
{
*tempWordPtr++ = grbg;
nextOfBgr = 2;
}
//no break
case 2:
if (tempWordPtr < wordPtrLimit)
{
*tempWordPtr++ = rbgr;
nextOfBgr = 0;
}
}
while (tempWordPtr < wordPtrLimit)
{
*tempWordPtr++ = bgrb;
*tempWordPtr++ = grbg;
*tempWordPtr++ = rbgr;
}
for (tempPixelPtr = (TUint8*)tempWordPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr++)
{
tempPixelPtr[0] = bgr[nextOfBgr++];
if (nextOfBgr > 2)
nextOfBgr = 0;
}
pixelPtr += scanLineBytes;
pixelPtrLimit += scanLineBytes;
}
}
/**
Writes a specific colour to the screen, optimised to use mem fill if the colour is shade of grey
and word aligned access the three possible combinations of the colour bytes.
*/
void CDrawTwentyFourBppBitmap::WriteRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
{
const TInt scanLineBytes = iScanLineBytes;
const TInt byteLength = aLength * 3;
TUint8* pixelPtr = PixelAddress(aX,aY);
TUint8* pixelRowPtrLimit = pixelPtr + (aHeight * scanLineBytes);
TUint8 r = TUint8(aColor.Red());
TUint8 g = TUint8(aColor.Green());
TUint8 b = TUint8(aColor.Blue());
if ((r == g) && (g == b))
{
while (pixelPtr < pixelRowPtrLimit)
{
Mem::Fill(pixelPtr,byteLength,r);
pixelPtr += scanLineBytes;
}
}
else
{
WriteTwentyFourBppColourAsWords(r, g, b, pixelPtr, byteLength, pixelRowPtrLimit, scanLineBytes);
}
}
void CDrawTwentyFourBppBitmap::WriteRgbMultiXOR(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
TUint8* pixelPtrLimit = pixelPtr + (aLength * 3);
TUint8* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineBytes);
TUint8 r = TUint8(aColor.Red());
TUint8 g = TUint8(aColor.Green());
TUint8 b = TUint8(aColor.Blue());
while (pixelPtr < pixelRowPtrLimit)
{
for (TUint8* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr += 3)
{
tempPixelPtr[0] ^= b;
tempPixelPtr[1] ^= g;
tempPixelPtr[2] ^= r;
}
pixelPtr += iScanLineBytes;
pixelPtrLimit += iScanLineBytes;
}
}
void CDrawTwentyFourBppBitmap::WriteRgbMultiAND(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
TUint8* pixelPtrLimit = pixelPtr + (aLength * 3);
TUint8* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineBytes);
TUint8 r = TUint8(aColor.Red());
TUint8 g = TUint8(aColor.Green());
TUint8 b = TUint8(aColor.Blue());
while (pixelPtr < pixelRowPtrLimit)
{
for (TUint8* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr += 3)
{
tempPixelPtr[0] &= b;
tempPixelPtr[1] &= g;
tempPixelPtr[2] &= r;
}
pixelPtr += iScanLineBytes;
pixelPtrLimit += iScanLineBytes;
}
}
void CDrawTwentyFourBppBitmap::WriteRgbMultiOR(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
TUint8* pixelPtrLimit = pixelPtr + (aLength * 3);
TUint8* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineBytes);
TUint8 r = TUint8(aColor.Red());
TUint8 g = TUint8(aColor.Green());
TUint8 b = TUint8(aColor.Blue());
while (pixelPtr < pixelRowPtrLimit)
{
for (TUint8* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr += 3)
{
tempPixelPtr[0] |= b;
tempPixelPtr[1] |= g;
tempPixelPtr[2] |= r;
}
pixelPtr += iScanLineBytes;
pixelPtrLimit += iScanLineBytes;
}
}
void CDrawTwentyFourBppBitmap::WriteRgbAlphaMulti(TInt aX,TInt aY,TInt aLength,TRgb aColor,const TUint8* aMaskBuffer)
{
DeOrientate(aX,aY);
TUint8* pixelPtr = PixelAddress(aX,aY);
const TInt pixelPtrInc = PixelAddressIncrement();
const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
if (iShadowMode)
Shadow(aColor);
const TInt red = aColor.Red();
const TInt green = aColor.Green();
const TInt blue = aColor.Blue();
while (aMaskBuffer < maskBufferPtrLimit)
{
if(aMaskBuffer[0])
{
TRgb pixelClr;
if(aMaskBuffer[0] != 0xff)
{
pixelClr = AlphaBlend(red, green, blue, TRgb(pixelPtr[2], pixelPtr[1], pixelPtr[0]), aMaskBuffer[0]);
}
else
{
pixelClr = aColor;
}
pixelPtr[0] = TUint8(pixelClr.Blue());
pixelPtr[1] = TUint8(pixelClr.Green());
pixelPtr[2] = TUint8(pixelClr.Red());
}
pixelPtr += pixelPtrInc;
aMaskBuffer++;
}
}
void CDrawTwentyFourBppBitmap::MapColorToUserDisplayMode(TRgb& aColor)
{
switch (iUserDispMode)
{
case EGray2:
aColor = TRgb::_Gray2(aColor._Gray2());
break;
case EGray4:
aColor = TRgb::_Gray4(aColor._Gray4());
break;
case EGray16:
aColor = TRgb::_Gray16(aColor._Gray16());
break;
case EGray256:
aColor = TRgb::_Gray256(aColor._Gray256());
break;
case EColor16:
aColor = TRgb::Color16(aColor.Color16());
break;
case EColor256:
aColor = TRgb::Color256(aColor.Color256());
break;
case EColor4K:
aColor = TRgb::_Color4K(aColor._Color4K());
break;
case EColor64K:
aColor = TRgb::_Color64K(aColor._Color64K());
break;
default:
break;
}
}
void CDrawTwentyFourBppBitmap::MapBufferToUserDisplayMode(TInt aLength,TUint32* aBuffer)
{
TUint8* bufferPtr = (TUint8*)aBuffer;
const TUint8* bufferLimit = bufferPtr + (aLength * 3);
switch (iUserDispMode)
{
case EGray2:
while (bufferPtr < bufferLimit)
{
TInt blue = bufferPtr[0];
TInt green = bufferPtr[1];
TInt red = bufferPtr[2];
TRgb color(red,green,blue);
color = TRgb::_Gray2(color._Gray2());
bufferPtr[0] = TUint8(color.Blue());
bufferPtr[1] = TUint8(color.Green());
bufferPtr[2] = TUint8(color.Red());
bufferPtr += 3;
}
break;
case EGray4:
while (bufferPtr < bufferLimit)
{
TInt blue = bufferPtr[0];
TInt green = bufferPtr[1];
TInt red = bufferPtr[2];
TRgb color(red,green,blue);
color = TRgb::_Gray4(color._Gray4());
bufferPtr[0] = TUint8(color.Blue());
bufferPtr[1] = TUint8(color.Green());
bufferPtr[2] = TUint8(color.Red());
bufferPtr += 3;
}
break;
case EGray16:
while (bufferPtr < bufferLimit)
{
TInt blue = bufferPtr[0];
TInt green = bufferPtr[1];
TInt red = bufferPtr[2];
TRgb color(red,green,blue);
color = TRgb::_Gray16(color._Gray16());
bufferPtr[0] = TUint8(color.Blue());
bufferPtr[1] = TUint8(color.Green());
bufferPtr[2] = TUint8(color.Red());
bufferPtr += 3;
}
break;
case EGray256:
while (bufferPtr < bufferLimit)
{
TInt blue = bufferPtr[0];
TInt green = bufferPtr[1];
TInt red = bufferPtr[2];
TRgb color(red,green,blue);
color = TRgb::_Gray256(color._Gray256());
bufferPtr[0] = TUint8(color.Blue());
bufferPtr[1] = TUint8(color.Green());
bufferPtr[2] = TUint8(color.Red());
bufferPtr += 3;
}
break;
case EColor16:
while (bufferPtr < bufferLimit)
{
TInt blue = bufferPtr[0];
TInt green = bufferPtr[1];
TInt red = bufferPtr[2];
TRgb color(red,green,blue);
color = TRgb::Color16(color.Color16());
bufferPtr[0] = TUint8(color.Blue());
bufferPtr[1] = TUint8(color.Green());
bufferPtr[2] = TUint8(color.Red());
bufferPtr += 3;
}
break;
case EColor256:
while (bufferPtr < bufferLimit)
{
TInt blue = bufferPtr[0];
TInt green = bufferPtr[1];
TInt red = bufferPtr[2];
TRgb color(red,green,blue);
color = TRgb::Color256(color.Color256());
bufferPtr[0] = TUint8(color.Blue());
bufferPtr[1] = TUint8(color.Green());
bufferPtr[2] = TUint8(color.Red());
bufferPtr += 3;
}
break;
case EColor4K:
while (bufferPtr < bufferLimit)
{
TInt blue = bufferPtr[0];
TInt green = bufferPtr[1];
TInt red = bufferPtr[2];
TRgb color(red,green,blue);
color = TRgb::_Color4K(color._Color4K());
bufferPtr[0] = TUint8(color.Blue());
bufferPtr[1] = TUint8(color.Green());
bufferPtr[2] = TUint8(color.Red());
bufferPtr += 3;
}
break;
case EColor64K:
while (bufferPtr < bufferLimit)
{
TInt blue = bufferPtr[0];
TInt green = bufferPtr[1];
TInt red = bufferPtr[2];
TRgb color(red,green,blue);
color = TRgb::_Color64K(color._Color64K());
bufferPtr[0] = TUint8(color.Blue());
bufferPtr[1] = TUint8(color.Green());
bufferPtr[2] = TUint8(color.Red());
bufferPtr += 3;
}
break;
default:
break;
}
}
TInt CDrawTwentyFourBppBitmap::WriteRgbOutlineAndShadow(TInt aX, TInt aY, const TInt aLength,
TUint32 aOutlinePenColor, TUint32 aShadowColor,
TUint32 aFillColor, const TUint8* aDataBuffer)
{
DeOrientate(aX,aY);
TUint8* pixelPtr = PixelAddress(aX,aY);
const TInt pixelPtrInc = PixelAddressIncrement();
const TUint8* dataBufferPtrLimit = aDataBuffer + aLength;
TInt blendedRedColor;
TInt blendedGreenColor;
TInt blendedBlueColor;
TUint8 index = 0;
TRgb finalColor;
TRgb outlinePenColor;
outlinePenColor.SetInternal(aOutlinePenColor);
TRgb shadowColor;
shadowColor.SetInternal(aShadowColor);
TRgb fillColor;
fillColor.SetInternal(aFillColor);
const TInt redOutlinePenColor = outlinePenColor.Red();
const TInt redShadowColor = shadowColor.Red();
const TInt redFillColor = fillColor.Red();
const TInt greenOutlinePenColor = outlinePenColor.Green();
const TInt greenShadowColor = shadowColor.Green();
const TInt greenFillColor = fillColor.Green();
const TInt blueOutlinePenColor = outlinePenColor.Blue();
const TInt blueShadowColor = shadowColor.Blue();
const TInt blueFillColor = fillColor.Blue();
const TInt alpha = aOutlinePenColor >> 24;
while (aDataBuffer < dataBufferPtrLimit)
{
index = *aDataBuffer++;
if (255 == FourColorBlendLookup[index][KBackgroundColorIndex])
{
//background colour
//No drawing required so move on to next pixel.
pixelPtr += pixelPtrInc;
continue;
}
else if (255 == FourColorBlendLookup[index][KFillColorIndex])
{
//fill colour
finalColor.SetInternal(aFillColor);
}
else if (255 == FourColorBlendLookup[index][KShadowColorIndex])
{
//Shadow colour
finalColor.SetInternal(aShadowColor);
}
else if (255 == FourColorBlendLookup[index][KOutlineColorIndex])
{
//Outline colour
finalColor.SetInternal(aOutlinePenColor);
}
else
{
TRgb backgroundColor = TRgb::_Color16M(TRgb(pixelPtr[2], pixelPtr[1], pixelPtr[0])._Color16M());
blendedRedColor = (redOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] +
redShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
redFillColor * FourColorBlendLookup[index][KFillColorIndex] +
backgroundColor.Red() * FourColorBlendLookup[index][KBackgroundColorIndex]) >> 8;
blendedGreenColor = (greenOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] +
greenShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
greenFillColor * FourColorBlendLookup[index][KFillColorIndex] +
backgroundColor.Green() * FourColorBlendLookup[index][KBackgroundColorIndex]) >> 8;
blendedBlueColor = (blueOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] +
blueShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
blueFillColor * FourColorBlendLookup[index][KFillColorIndex] +
backgroundColor.Blue() * FourColorBlendLookup[index][KBackgroundColorIndex]) >> 8;
if (alpha != 0xff)
{
TRgb alphablend = AlphaBlend(blendedRedColor, blendedGreenColor, blendedBlueColor, TRgb(pixelPtr[2], pixelPtr[1], pixelPtr[0]), alpha);
pixelPtr[0] = TUint8(alphablend.Blue());
pixelPtr[1] = TUint8(alphablend.Green());
pixelPtr[2] = TUint8(alphablend.Red());
}
else
{
//opaque
pixelPtr[0] = TUint8(blendedBlueColor);
pixelPtr[1] = TUint8(blendedGreenColor);
pixelPtr[2] = TUint8(blendedRedColor);
}
pixelPtr += pixelPtrInc;
continue;
}
if (alpha != 0xff)
{
TRgb alphablend = AlphaBlend(finalColor, TRgb(pixelPtr[2], pixelPtr[1], pixelPtr[0]), alpha);
pixelPtr[0] = TUint8(alphablend.Blue());
pixelPtr[1] = TUint8(alphablend.Green());
pixelPtr[2] = TUint8(alphablend.Red());
}
else
{
pixelPtr[0] = TUint8(finalColor.Blue());
pixelPtr[1] = TUint8(finalColor.Green());
pixelPtr[2] = TUint8(finalColor.Red());
}
pixelPtr += pixelPtrInc;
}
return KErrNone;
}
void CDrawTwentyFourBppBitmap::BlendRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
{
const TInt sourceAlpha = aColor.Alpha();
if (sourceAlpha == 0xFF) //Fully opaque
{
WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
return;
}
else if (sourceAlpha == 0x00) //Fully transparent
{
return;
}
else //Perform alpha blending
{
TUint8* pixelPtr = PixelAddress(aX,aY);
const TInt pixelPtrInc = PixelAddressIncrement();
TUint8* pixelPtrEnd = pixelPtr + (aLength * pixelPtrInc);
TUint8 dr;
TUint8 dg;
TUint8 db;
//Perform pre-multiplication on values from aColor
const TUint8 pmsr = (sourceAlpha * aColor.Red()) / 255;
const TUint8 pmsg = (sourceAlpha * aColor.Green()) / 255;
const TUint8 pmsb = (sourceAlpha * aColor.Blue()) / 255;
for (TInt ii = 0 ; ii <= aHeight; ii++)
{
while (pixelPtr != pixelPtrEnd)
{
dr = pixelPtr[2];
dg = pixelPtr[1];
db = pixelPtr[0];
//Target has no alpha channel so assume to be 0xFF (opaque)
pixelPtr[0] = pmsb + ((0xFF-sourceAlpha) * db)/255;
pixelPtr[1] = pmsg + ((0xFF-sourceAlpha) * dg)/255;
pixelPtr[2] = pmsr + ((0xFF-sourceAlpha) * dr)/255;
pixelPtr+=pixelPtrInc;
}
pixelPtr = PixelAddress(aX, ii+aY);
pixelPtrEnd = pixelPtr + (aLength * pixelPtrInc);
}
}
}