// 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"
// CDrawEightBppBitmapCommon
//EColor256 screen/bitmap device might be scaled.
//In this case right-bottom coordinate might go outside the drawing rectangle.
//Then - we need to check that we do not try to draw something outside the drawing rectangle.
//Initializes iSize, iDrawRect, iLongWidth, 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 CDrawEightBppBitmapCommon::SetSize(const TSize& aSize)
{
CDrawBitmap::SetSize(aSize);
__ASSERT_DEBUG(iSize == aSize, User::Invariant());
iLongWidth = (iSize.iWidth + 3) & ~3;
iScanLineWords = iLongWidth / 4;
}
TInt CDrawEightBppBitmapCommon::Construct(TSize aSize, TInt aStride)
{
iBits = NULL;
CDrawBitmap::SetSize(aSize);
__ASSERT_DEBUG(iSize == aSize, User::Invariant());
if (aStride & 3)
return KErrArgument;
iLongWidth = aStride;
if (iLongWidth < aSize.iWidth)
return KErrArgument;
iScanLineWords = aStride >> 2;
TInt size = Max(aSize.iWidth,aSize.iHeight);
if(size < 0)
return KErrArgument;
iScanLineBuffer = (TUint32*)(User::Heap().Alloc(size));
if(iScanLineBuffer == NULL)
return KErrNoMemory;
return KErrNone;
}
//aX, aY - physical coordinates
TUint8* CDrawEightBppBitmapCommon::PixelAddress(TInt aX,TInt aY) const
{
return (TUint8*)iBits + aY * iLongWidth + aX;
}
void CDrawEightBppBitmapCommon::InvertBuffer(TInt aLength,TUint32* aBuffer)
{
const TUint32* limit = aBuffer + (aLength + 3) / 4;
while (aBuffer < limit)
*aBuffer++ ^= 0xffffffff;
}
//CDrawEightBppBitmapCommon::ReadLine() called from CDrawBitmap::ReadLine()
//aX and aY - physical coordinates.
//Reads aLength pixel values and places them in aBuffer.
//aBuffer size should be at least aLength.
void CDrawEightBppBitmapCommon::ReadLine(TInt aX,TInt aY,TInt aLength,TAny* aBuffer) const
{
const TUint8* pixelPtr = PixelAddress(aX,aY);
if (iOrientation == EOrientationNormal && iScalingOff)
Mem::Copy(aBuffer,pixelPtr,aLength);
else
{
register TInt pixelPtrInc = LogicalPixelAddressIncrement();
TUint8* bufferPtr = static_cast <TUint8*> (aBuffer);
const TUint8* bufferPtrLimit = bufferPtr + aLength;
while (bufferPtr < bufferPtrLimit)
{
*bufferPtr++ = *pixelPtr;
pixelPtr += pixelPtrInc;
}
}
}
//CDrawEightBppBitmapCommon::WriteRgb() called from exported CDrawBitmap::WriteRgb()
//aX, aY - physical coordinates
void CDrawEightBppBitmapCommon::WriteRgb(TInt aX,TInt aY,TUint8 aPixel)
{
register TUint8* pixelAddr = PixelAddress(aX, aY);
if(iScalingOff)
{
*pixelAddr = aPixel;
}
else
{
const TUint8* bitsStart = reinterpret_cast <const TUint8*> (iBits);
const TUint8* bitsEnd = bitsStart + iLongWidth * iSize.iHeight;
const TUint8* pixelRowPtrLimit = bitsStart + (aY + 1) * iLongWidth;
SetPixels(pixelAddr, aPixel, pixelRowPtrLimit, bitsStart, bitsEnd);
}
}
//CDrawEightBppBitmapCommon::WriteBinary() called from exported CDrawBitmap::WriteBinary()
//aX, aY - logical coordinates
//"aData" parameter has "aHeight" 32 bits words
//"aLength" parameter tells how many bits (up to 32) has to be used from each 32 bit word
//This method is used for bitmap font symbols drawing
//One possible optimization: If "no scaling" And "pixelPtrInc == 1" Then
//writing could be made on 32 bits words (they has to be aligned before the operation)
void CDrawEightBppBitmapCommon::WriteBinary(TInt aX,TInt aY,TUint32* aData,TInt aLength,
TInt aHeight,TUint8 aPixel)
{
DeOrientate(aX,aY);//aX, aY - physical coordinates
TInt pixelInc;
TInt rowInc;
SetPixelInc(pixelInc, rowInc);
const TUint32* dataLimit = aData + aHeight;
register TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
TUint8* pixelPtr = PixelAddress(aX,aY);
const TUint8* bitsStart = reinterpret_cast <const TUint8*> (iBits);
const TUint8* bitsEnd = bitsStart + iLongWidth * iSize.iHeight;
TInt orgY = aY;
while (aData < dataLimit)
{
register TUint32 dataWord = *aData++;
register TUint32 dataMask = 1;
register TUint8* tempPixelPtr = pixelPtr;
if(iScalingOff)
{
while (dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
*tempPixelPtr = aPixel;
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
}
}
else
{
while (dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
const TUint8* pixelRowPtrLimit = bitsStart + (aY + 1) * iLongWidth;
SetPixels(tempPixelPtr, aPixel, pixelRowPtrLimit, bitsStart, bitsEnd);
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
IncScaledY(aY);
}
}
pixelPtr += rowInc;
IncScaledY(aY, orgY);
}
}
//CDrawEightBppBitmapCommon::WriteBinaryOp() called from exported CDrawBitmap::WriteBinary()
//aX, aY - logical coordinates
//"aData" parameter has "aHeight" 32 bits words
//"aLength" parameter tells how many bits (up to 32) has to be used from each 32 bit word
//This method is used for bitmap font symbols drawing
//One possible optimization: If "no scaling" And "pixelPtrInc == 1" Then
//writing could be made on 32 bits words (they has to be aligned before the operation)
void CDrawEightBppBitmapCommon::WriteBinaryOp(TInt aX,TInt aY,TUint32* aData,TInt aLength,
TInt aHeight,TUint8 aPixel,
CGraphicsContext::TDrawMode aDrawMode)
{
if(aLength <= 0)
{
return;
}
DeOrientate(aX,aY);//aX, aY - physical coordinates
TUint8* pixelPtr = PixelAddress(aX,aY);
const TUint32* dataPtrLimit = aData + aHeight;
register TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
TInt pixelInc;
TInt rowInc;
SetPixelInc(pixelInc, rowInc);
const TUint8* bitsStart = reinterpret_cast <const TUint8*> (iBits);
const TUint8* bitsEnd = bitsStart + iLongWidth * iSize.iHeight;
TInt orgY = aY;
if(aPixel)
{
while(aData < dataPtrLimit)
{
register TUint32 dataWord = *aData++;
register TUint32 dataMask = 1;
register TUint8* tempPixelPtr = pixelPtr;
if(iScalingOff)
{
while(dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
if(aDrawMode==CGraphicsContext::EDrawModeXOR)
{
*tempPixelPtr ^= aPixel;
}
else if(aDrawMode==CGraphicsContext::EDrawModeAND)
{
*tempPixelPtr &= aPixel;
}
else if(aDrawMode==CGraphicsContext::EDrawModeOR)
{
*tempPixelPtr |= aPixel;
}
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
}
}
else
{
while(dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
const TUint8* pixelRowPtrLimit = bitsStart + (aY + 1) * iLongWidth;
if(aDrawMode==CGraphicsContext::EDrawModeXOR)
{
XORPixels(tempPixelPtr, aPixel, pixelRowPtrLimit, bitsStart, bitsEnd);
}
else if(aDrawMode==CGraphicsContext::EDrawModeAND)
{
ANDPixels(tempPixelPtr, aPixel, pixelRowPtrLimit, bitsStart, bitsEnd);
}
else if(aDrawMode==CGraphicsContext::EDrawModeOR)
{
ORPixels(tempPixelPtr, aPixel, pixelRowPtrLimit, bitsStart, bitsEnd);
}
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
IncScaledY(aY);
}
}
pixelPtr += rowInc;
IncScaledY(aY, orgY);
}
}
else if(aDrawMode==CGraphicsContext::EDrawModeAND)
{
while(aData < dataPtrLimit)
{
register TUint32 dataWord = *aData++;
register TUint32 dataMask = 1;
register TUint8* tempPixelPtr = pixelPtr;
if(iScalingOff)
{
while(dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
*tempPixelPtr = 0;
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
}
}
else
{
while(dataMask != dataMaskLimit)
{
if(dataWord & dataMask)
{
const TUint8* pixelRowPtrLimit = bitsStart + (aY + 1) * iLongWidth;
SetPixels(tempPixelPtr, TUint8(0), pixelRowPtrLimit, bitsStart, bitsEnd);
}
tempPixelPtr += pixelInc;
dataMask <<= 1;
}
}
pixelPtr += rowInc;
IncScaledY(aY, orgY);
}
}
}
//aX, aY - logical coordinates
//"aData" parameter has 32 bits words
//"aLength" parameter tells how many pixels have to be written
//This method is used for bitmap font symbols vertical drawing
//The method should not be called if the scaling is ON!
void CDrawEightBppBitmapCommon::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aData,
TInt aLength,TUint8 aPixel,TBool aUp)
{
__ASSERT_DEBUG(iScalingOff, User::Invariant());
DeOrientate(aX,aY);//aX, aY - physical coordinates
TInt scanlineByteLength;
switch(iOrientation)
{
case EOrientationNormal:
scanlineByteLength = iLongWidth;
break;
case EOrientationRotated90:
scanlineByteLength = -1;
break;
case EOrientationRotated180:
scanlineByteLength = -iLongWidth;
break;
default: // EOrientationRotated270
scanlineByteLength = 1;
}
if (aUp)
scanlineByteLength = -scanlineByteLength;
register TUint8* pixelPtr = PixelAddress(aX,aY);
const TUint8* pixelPtrLimit = pixelPtr + aLength * scanlineByteLength;
register TUint32 dataWord = *aData;
register TUint32 dataMask = 1;
while(pixelPtr != pixelPtrLimit)
{
if(!dataMask)
{
dataMask = 1;
aData++;
dataWord = *aData;
}
if(dataWord & dataMask)
{
*pixelPtr = aPixel;
}
dataMask <<= 1;
pixelPtr += scanlineByteLength;
}
}
//CDrawEightBppBitmapCommon::WriteLine() called from CDrawBitmap::WriteLine()
//aX and aY - physical coordinates
void CDrawEightBppBitmapCommon::WriteLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
if (iOrientation == EOrientationNormal && iScalingOff)
{
Mem::Copy(pixelPtr,aBuffer,aLength);
}
else
{
register TInt pixelPtrInc = LogicalPixelAddressIncrement();
TUint8* bufferPtr = reinterpret_cast <TUint8*> (aBuffer);
const TUint8* bufferPtrLimit = bufferPtr + aLength;
if(iScalingOff)
{
while(bufferPtr < bufferPtrLimit)
{
*pixelPtr = *bufferPtr++;
pixelPtr += pixelPtrInc;
}
}
else
{
const TUint8* bitsStart = reinterpret_cast <const TUint8*> (iBits);
const TUint8* bitsEnd = bitsStart + iLongWidth * iSize.iHeight;
while(bufferPtr < bufferPtrLimit)
{
const TUint8* pixelRowPtrLimit = bitsStart + (aY + 1) * iLongWidth;
SetPixels(pixelPtr, *bufferPtr++, pixelRowPtrLimit, bitsStart, bitsEnd);
pixelPtr += pixelPtrInc;
IncScaledY(aY);
}
}
}
}
//CDrawEightBppBitmapCommon::WriteLineXOR() called from CDrawBitmap::WriteLine()
//aX and aY - physical coordinates
//One possible optimization: If "no scaling" And "pixelPtrInc == 1" Then
//XOR could be made on 32 bits words (they has to be aligned before the operation)
void CDrawEightBppBitmapCommon::WriteLineXOR(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
register TInt pixelPtrInc = LogicalPixelAddressIncrement();
TUint8* bufferPtr = reinterpret_cast <TUint8*> (aBuffer);
const TUint8* bufferPtrLimit = bufferPtr + aLength;
if(iScalingOff)
{
while(bufferPtr < bufferPtrLimit)
{
*pixelPtr ^= *bufferPtr++;
pixelPtr += pixelPtrInc;
}
}
else
{
const TUint8* bitsStart = reinterpret_cast <const TUint8*> (iBits);
const TUint8* bitsEnd = bitsStart + iLongWidth * iSize.iHeight;
while(bufferPtr < bufferPtrLimit)
{
const TUint8* pixelRowPtrLimit = bitsStart + (aY + 1) * iLongWidth;
XORPixels(pixelPtr, *bufferPtr++, pixelRowPtrLimit, bitsStart, bitsEnd);
pixelPtr += pixelPtrInc;
IncScaledY(aY);
}
}
}
//CDrawEightBppBitmapCommon::WriteLineAND() called from CDrawBitmap::WriteLine()
//aX and aY - deorientated and scaled
//aLength - not scaled
//One possible optimization: If "no scaling" And "pixelPtrInc == 1" Then
//AND could be made on 32 bits words (they has to be aligned before the operation)
void CDrawEightBppBitmapCommon::WriteLineAND(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
register TInt pixelPtrInc = LogicalPixelAddressIncrement();
TUint8* bufferPtr = reinterpret_cast <TUint8*> (aBuffer);
const TUint8* bufferPtrLimit = bufferPtr + aLength;
if(iScalingOff)
{
while(bufferPtr < bufferPtrLimit)
{
*pixelPtr &= *bufferPtr++;
pixelPtr += pixelPtrInc;
}
}
else
{
const TUint8* bitsStart = reinterpret_cast <const TUint8*> (iBits);
const TUint8* bitsEnd = bitsStart + iLongWidth * iSize.iHeight;
while(bufferPtr < bufferPtrLimit)
{
const TUint8* pixelRowPtrLimit = bitsStart + (aY + 1) * iLongWidth;
ANDPixels(pixelPtr, *bufferPtr++, pixelRowPtrLimit, bitsStart, bitsEnd);
pixelPtr += pixelPtrInc;
IncScaledY(aY);
}
}
}
//CDrawEightBppBitmapCommon::WriteLineOR() called from CDrawBitmap::WriteLine()
//aX and aY - physical coordinates
//One possible optimization: If "no scaling" And "pixelPtrInc == 1" Then
//OR could be made on 32 bits words (they has to be aligned before the operation)
void CDrawEightBppBitmapCommon::WriteLineOR(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
{
TUint8* pixelPtr = PixelAddress(aX,aY);
register TInt pixelPtrInc = LogicalPixelAddressIncrement();
TUint8* bufferPtr = reinterpret_cast <TUint8*> (aBuffer);
const TUint8* bufferPtrLimit = bufferPtr + aLength;
if(iScalingOff)
{
while(bufferPtr < bufferPtrLimit)
{
*pixelPtr |= *bufferPtr++;
pixelPtr += pixelPtrInc;
}
}
else
{
const TUint8* bitsStart = reinterpret_cast <const TUint8*> (iBits);
const TUint8* bitsEnd = bitsStart + iLongWidth * iSize.iHeight;
while(bufferPtr < bufferPtrLimit)
{
const TUint8* pixelRowPtrLimit = bitsStart + (aY + 1) * iLongWidth;
ORPixels(pixelPtr, *bufferPtr++, pixelRowPtrLimit, bitsStart, bitsEnd);
pixelPtr += pixelPtrInc;
IncScaledY(aY);
}
}
}
//CDrawEightBppBitmapCommon::WriteRgbMulti() called from CDrawBitmap::WriteRgbMulti()
//aX and aY - physical coordinates
//aLength and aRows - physical length and rows
void CDrawEightBppBitmapCommon::WriteRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aRows,
TUint8 aPixel)
{
register TInt longWidth = iLongWidth;
TUint8* pixelPtr = PixelAddress(aX,aY);
const TUint8* pixelRowPtrLimit = pixelPtr + aRows * longWidth;
register const TUint8* bitsEnd = reinterpret_cast <const TUint8*> (iBits) + iLongWidth * iSize.iHeight;
if(pixelRowPtrLimit >= bitsEnd)
{
pixelRowPtrLimit = bitsEnd;
}
while (pixelPtr < pixelRowPtrLimit)
{
Mem::Fill(pixelPtr,aLength,aPixel);
pixelPtr += longWidth;
}
}
//CDrawEightBppBitmapCommon::WriteRgbMultiXOR() called from CDrawBitmap::WriteRgbMulti()
//aX and aY - physical coordinates
//aLength and aRows - physical length and rows
void CDrawEightBppBitmapCommon::WriteRgbMultiXOR(TInt aX,TInt aY,TInt aLength,TInt aRows,
TUint8 aPixel)
{
register TInt longWidth = iLongWidth;
TUint8* pixelPtr = PixelAddress(aX,aY);
TUint8* pixelPtrLimit = pixelPtr + aLength;
const TUint8* pixelRowPtrLimit = pixelPtr + aRows * longWidth;
register const TUint8* bitsEnd = reinterpret_cast <const TUint8*> (iBits) + iLongWidth * iSize.iHeight;
if(pixelRowPtrLimit >= bitsEnd)
{
pixelRowPtrLimit = bitsEnd;
}
while (pixelPtr < pixelRowPtrLimit)
{
TUint8* tempPixelPtr = pixelPtr;
while (tempPixelPtr < pixelPtrLimit)
*tempPixelPtr++ ^= aPixel;
pixelPtr += longWidth;
pixelPtrLimit += longWidth;
}
}
//CDrawEightBppBitmapCommon::WriteRgbMultiAND() called from CDrawBitmap::WriteRgbMulti()
//aX and aY - physical coordinates
//aLength and aRows - physical length and rows
void CDrawEightBppBitmapCommon::WriteRgbMultiAND(TInt aX,TInt aY,TInt aLength,TInt aRows,
TUint8 aPixel)
{
register TInt longWidth = iLongWidth;
TUint8* pixelPtr = PixelAddress(aX,aY);
const TUint8* pixelPtrLimit = pixelPtr + aLength;
const TUint8* pixelRowPtrLimit = pixelPtr + aRows * longWidth;
register const TUint8* bitsEnd = reinterpret_cast <const TUint8*> (iBits) + iLongWidth * iSize.iHeight;
if(pixelRowPtrLimit >= bitsEnd)
{
pixelRowPtrLimit = bitsEnd;
}
while (pixelPtr < pixelRowPtrLimit)
{
TUint8* tempPixelPtr = pixelPtr;
while (tempPixelPtr < pixelPtrLimit)
*tempPixelPtr++ &= aPixel;
pixelPtr += longWidth;
pixelPtrLimit += longWidth;
}
}
//CDrawEightBppBitmapCommon::WriteRgbMultiOR() called from CDrawBitmap::WriteRgbMulti()
//aX and aY - physical coordinates
//aLength and aRows - physical length and rows
void CDrawEightBppBitmapCommon::WriteRgbMultiOR(TInt aX,TInt aY,TInt aLength,TInt aRows,TUint8 aPixel)
{
register TInt longWidth = iLongWidth;
TUint8* pixelPtr = PixelAddress(aX,aY);
TUint8* pixelPtrLimit = pixelPtr + aLength;
const TUint8* pixelRowPtrLimit = pixelPtr + aRows * longWidth;
register const TUint8* bitsEnd = reinterpret_cast <const TUint8*> (iBits) + iLongWidth * iSize.iHeight;
if(pixelRowPtrLimit >= bitsEnd)
{
pixelRowPtrLimit = bitsEnd;
}
while (pixelPtr < pixelRowPtrLimit)
{
TUint8* tempPixelPtr = pixelPtr;
while (tempPixelPtr < pixelPtrLimit)
*tempPixelPtr++ |= aPixel;
pixelPtr += longWidth;
pixelPtrLimit += longWidth;
}
}
/**
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 CDrawEightBppBitmapCommon::GetInterface(TInt aInterfaceId, TAny*& aInterface)
{
aInterface = NULL;
TInt ret = KErrNotSupported;
if (aInterfaceId == KFastBlit2InterfaceID)
{
aInterface = static_cast<MFastBlit2*>(this);
ret = KErrNone;
}
else
return CDrawBitmap::GetInterface(aInterfaceId, aInterface);
return ret;
}
/**
CDrawEightBppBitmapCommon::WriteBitmapBlock() implementation.
@internalTechnology
@see MFastBlit2::WriteBitmapBlock()
*/
TInt CDrawEightBppBitmapCommon::WriteBitmapBlock(const TPoint& aDest,
CFbsDrawDevice* aSrcDrawDevice,
const TRect& aSrcRect)
{
__ASSERT_DEBUG(aSrcDrawDevice && ((aSrcDrawDevice->DisplayMode()==EColor256) || (aSrcDrawDevice->DisplayMode()==EGray256)), Panic(EScreenDriverPanicInvalidParameter));
TAny* interface=NULL;
TInt ret = aSrcDrawDevice->GetInterface(KFastBlit2InterfaceID, interface);
if (ret != KErrNone)
{
return KErrNotSupported;
}
TAny* interface1=NULL;
ret = aSrcDrawDevice->GetInterface(KScalingSettingsInterfaceID, interface1);
if(ret != KErrNone || (interface1 && !reinterpret_cast<MScalingSettings*>(interface1)->IsScalingOff()))
{
return KErrNotSupported;
}
ret = aSrcDrawDevice->GetInterface(KOrientationInterfaceID, interface1);
if(ret != KErrNone || (interface1 && reinterpret_cast<MDrawDeviceOrientation*>(interface1)->Orientation() != 0))
{
return KErrNotSupported;
}
ret = aSrcDrawDevice->GetInterface(KDrawDeviceOriginInterfaceID, interface1);
if(ret != KErrNone)
{
return KErrNotSupported;
}
if(interface1)
{
TPoint pt;
reinterpret_cast<MDrawDeviceOrigin*>(interface1)->Get(pt);
if(pt.iX != 0 || pt.iY != 0)
{
return KErrNotSupported;
}
}
const TUint32* srcBase = reinterpret_cast<MFastBlit2*>(interface)->Bits();
__ASSERT_DEBUG(srcBase!=NULL, Panic(EScreenDriverPanicInvalidParameter));
TInt srcStride = aSrcDrawDevice->ScanLineBytes();
__ASSERT_DEBUG((srcStride&3)==0, Panic(EScreenDriverPanicInvalidParameter)); // stride is assumed to be a multiple of 4
TSize srcSize = aSrcDrawDevice->SizeInPixels();
return WriteBitmapBlock(aDest, srcBase, srcStride, srcSize, aSrcRect);
}
/**
CDrawEightBppBitmapCommon::WriteBitmapBlock() implementation.
@internalTechnology
@see MFastBlit2::WriteBitmapBlock()
*/
TInt CDrawEightBppBitmapCommon::WriteBitmapBlock(const TPoint& aDest,
const TUint32* aSrcBase,
TInt aSrcStride,
const TSize& aSrcSize,
const TRect& aSrcRect)
{
__ASSERT_DEBUG(aSrcBase, Panic(EScreenDriverPanicInvalidParameter));
__ASSERT_DEBUG((aSrcStride&3)==0, Panic(EScreenDriverPanicInvalidParameter));
__ASSERT_DEBUG(iBits, Panic(EScreenDriverPanicInvalidPointer));
if (iShadowMode!=NULL ||
(iUserDispMode!=NULL && iUserDispMode!=iDispMode) ||
iOrientation!=EOrientationNormal ||
!IsScalingOff() ||
!iOriginIsZero)
{
return KErrNotSupported;
}
__ASSERT_DEBUG(aSrcRect.iTl.iX >= 0, Panic(EScreenDriverPanicOutOfBounds));
__ASSERT_DEBUG(aSrcRect.iTl.iY >= 0, Panic(EScreenDriverPanicOutOfBounds));
__ASSERT_DEBUG(aSrcRect.iBr.iX <= aSrcSize.iWidth, Panic(EScreenDriverPanicOutOfBounds));
__ASSERT_DEBUG(aSrcRect.iBr.iY <= aSrcSize.iHeight, Panic(EScreenDriverPanicOutOfBounds));
__ASSERT_DEBUG(aDest.iX >= 0, Panic(EScreenDriverPanicOutOfBounds));
__ASSERT_DEBUG(aDest.iY >= 0, Panic(EScreenDriverPanicOutOfBounds));
__ASSERT_DEBUG((aDest.iX + aSrcRect.Width()) <= SizeInPixels().iWidth, Panic(EScreenDriverPanicOutOfBounds));
__ASSERT_DEBUG((aDest.iY + aSrcRect.Height()) <= SizeInPixels().iHeight, Panic(EScreenDriverPanicOutOfBounds));
const TInt srcStride8 = aSrcStride;
const TInt dstStride8 = iScanLineWords << 2;
if (aSrcSize.iWidth == aSrcRect.Width() &&
aSrcSize.iWidth == SizeInPixels().iWidth &&
srcStride8 == dstStride8)
{
// Optimum case - one memcpy
__ASSERT_DEBUG(aSrcRect.iTl.iX==0 && aDest.iX==0, Panic(EScreenDriverPanicInvalidParameter)); // this is implied by the above conditions
const TUint32* srcPtr = aSrcBase + (iScanLineWords * aSrcRect.iTl.iY);
TUint32* dstPtr = iBits + (iScanLineWords * aDest.iY);
const TInt length = aSrcStride * aSrcRect.Height();
Mem::Move(dstPtr, srcPtr, length);
return KErrNone;
}
// Sub-optimal case - one memcpy per line
const TUint8* srcPtr = (TUint8*)aSrcBase + (srcStride8 * aSrcRect.iTl.iY) + aSrcRect.iTl.iX;
TUint8* dstPtr = (TUint8*)iBits + (dstStride8 * aDest.iY ) + aDest.iX;
const TInt length = aSrcRect.Width();
TInt lines = aSrcRect.Height();
while (lines--)
{
Mem::Copy(dstPtr, srcPtr, length);
srcPtr += srcStride8;
dstPtr += dstStride8;
}
return KErrNone;
}
/**
CDrawEightBppBitmapCommon::Bits() implementation.
@internalTechnology
@see MFastBlit2::Bits()
*/
const TUint32* CDrawEightBppBitmapCommon::Bits() const
{
return iBits;
}