--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/screendriver/sbit/BMDRAW32A.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,708 @@
+// Copyright (c) 2004-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"
+
+/**
+Performs a blend based on the PD method, with 2* 16 bit in one 32 bit operation optimisation.
+Note that this method assumes both input s are NOT alpha pre multiplied, but the output IS pre multiplied.
+The mechanism of this method is non-standard and non-intuitive, and is being addressed in 9.3
+by developing distinct classes for the premultiplied and nonmultiplied cases.
+The mechanism remains hybrid to maintain compatibility and colour channel overflows caused by rounding
+overflows have been addressed.
+PD is basically CDest=CSrc*MulSrc+CDest*MulDest
+//A second optimisation is that multiplier value must be scaled from 0..255 to 0.0..1.0, this is 1/255 = 0.00392156.
+A second optimisation is that multiplier value must be scaled from 257..65535 to 0.0..1.0, this is 1/65535 = 0.0000152590.
+This used to be done by simply adding 1, giving 1..256/256
+but this allows overflows to occur when the fractional parts are added together.
+We want to keep adding the fractional parts as that gives a better result.
+Instead I am now using an approximation of 0.00392151, based on 255*257/256.
+To describe it imagine a "decimal" colour mode, where the channels count from 0..9, and 10-based operations are "efficient".
+We need 9 to generate 1.0 or 10/10 meaning "all".
+If we add 1, then we get 1..10 ==> 0.1 .. 1.0
+If we multiply by 1.1 then we get 0.0 .. 9.9.
+And finally add a 0.5 rounding to the result.
+I do this multiply after the CSrc*MulSrc, while I still have a 16bit intermediate result.
+It is possible to generate a faster, less accurate result by exhaustively finding
+the highest value that can be added instead of rb = rb+((rb>>8)&0x00ff00ff)+0x00800080; without causing an overflow.
+*/
+FORCEINLINE TUint32 OptimizedBlend32A(TUint32 aBeneath,TUint32 aSrcColor,TUint8 aMaskBuffer)
+ {
+ if(aMaskBuffer)
+ {
+ if(aMaskBuffer == 0xff) // opaque, so unchanged
+ {
+ //Still need to convert source to destination from non-multiplied to pre-multiplied
+ //But this code resolves to a copy. The ARM optimiser prefers shifts over big constants.
+ return (aSrcColor|(aMaskBuffer<<24));
+ }
+ else
+ {
+ //0, 1, 2, 3
+ //b, g, r, alpha
+
+ const TUint32 srcMult = aMaskBuffer;
+ TUint32 destMult = ((255 - aMaskBuffer) * ((aBeneath >> 24)));
+ //This gives a slightly more accurate result than ((aBeneath >> 24)+1)
+ destMult=destMult+(destMult>>8);
+ destMult+= 0x0080;
+ destMult >>= 8;
+
+ TUint32 rb =(((aSrcColor&0x00ff00ff)*srcMult)) + (((aBeneath&0x00ff00ff)*destMult));
+ rb = rb+((rb>>8)&0x00ff00ff);
+ rb+=0x00800080;
+ rb>>=8;
+ TUint32 ag = (((aSrcColor&0x0000ff00)*srcMult)) + (((aBeneath&0x0000ff00)*destMult));
+ ag>>=8; //Note that if alpha is processed here, this shift must be performed before the multiplies
+ ag = ag+((ag>>8)&0x00ff00ff);
+ ag+=0x00800080;
+ TUint32 aa = srcMult+destMult;
+ return (rb&0x00ff00ff) | (ag&0x0000ff00) | (aa << 24);
+
+ }
+ }
+ else // completely transparent
+ {
+ return aBeneath;
+ }
+
+ }
+
+TInt CDrawThirtyTwoBppBitmapAlpha::Construct(TSize aSize)
+ {
+ return Construct(aSize, aSize.iWidth << 2);
+ }
+
+TInt CDrawThirtyTwoBppBitmapAlpha::Construct(TSize aSize, TInt aStride)
+ {
+ iDispMode = EColor16MA;
+ return CDrawThirtyTwoBppBitmapCommon::Construct(aSize, aStride);
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::Shadow(TUint32& aColor)
+ {
+ TUint32 value = aColor & 0x00ffffff;
+ if (iShadowMode & EFade)
+ {
+#if defined(SYMBIAN_USE_FAST_FADING)
+ value = ((value >> 1) & ~0x00808080) + (SYMBIAN_USE_FAST_FADING);
+#else
+ const TInt wordFadeMapOffset = ((iFadeMapOffset & 0xff) << 16) | (iFadeMapOffset & 0xff);
+ const TInt rb = ((((value & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
+ const TInt g = ((((value & 0x0000ff00) * iFadeMapFactor) >> 16) + iFadeMapOffset) << 8;
+ value = rb | g;
+#endif
+ }
+
+ if (iShadowMode & EShadow)
+ {
+ const TInt r = (value & 0x00c00000) ? ((value & 0x00ff0000)-0x00400000) : 0;
+ const TInt g = (value & 0x0000c000) ? ((value & 0x0000ff00)-0x00004000) : 0;
+ const TInt b = (value & 0x000000c0) ? ((value & 0x000000ff)-0x00000040) : 0;
+ value = r | g | b;
+ }
+ // alpha is unchanged.
+ aColor = (aColor & 0xff000000) | value;
+ }
+
+/**
+MAlphaBlend::WriteRgbAlphaLine() implementation.
+@see MAlphaBlend::WriteRgbAlphaLine()
+*/
+void CDrawThirtyTwoBppBitmapAlpha::WriteRgbAlphaLine(TInt aX, TInt aY, TInt aLength,
+ const TUint8* aRgbBuffer,
+ const TUint8* aMaskBuffer,
+ MAlphaBlend::TShadowing aShadowing,
+ CGraphicsContext::TDrawMode /*aDrawMode*/)
+ {
+ // precondition for this function is that the aRgbBuffer lies on a word boundary
+ // Assert checks that the pointer is at a word boundary
+ __ASSERT_DEBUG(!(((TUint)aRgbBuffer) & 0x3), Panic(EScreenDriverPanicInvalidPointer));
+
+ DeOrientate(aX,aY);
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+ const TInt pixelPtrInc = PixelAddressIncrement();
+ const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
+
+ // The purpose of this conditional is to remove if statements from within the loop
+ // if shadow mode is not enabled and the UserDispMode is none or EColor16MA
+ if(!(iShadowMode & (EFade | EShadow)) && (iUserDispMode ==EColor16MA || iUserDispMode == ENone))
+ {
+ while (aMaskBuffer < maskBufferPtrLimit)
+ {
+ if(*aMaskBuffer)
+ {
+ *pixelPtr = OptimizedBlend32A(*pixelPtr, *((TUint32*)(aRgbBuffer)), *aMaskBuffer);
+ }
+ pixelPtr += pixelPtrInc;
+ aRgbBuffer += 4;
+ aMaskBuffer++;
+ }
+ }
+ else
+ {
+ while (aMaskBuffer < maskBufferPtrLimit)
+ {
+ if(*aMaskBuffer)
+ {
+ TUint32 srcColor = *((TUint32*)(aRgbBuffer));
+ if(aShadowing == MAlphaBlend::EShdwBefore)
+ {
+ Shadow(srcColor);
+ }
+
+ TUint32 pixelClr = 0x0;
+
+ pixelClr = OptimizedBlend32A(*pixelPtr, srcColor, *aMaskBuffer);
+
+ if(aShadowing == MAlphaBlend::EShdwAfter)
+ {
+ Shadow(pixelClr);
+ }
+
+ if(iUserDispMode !=EColor16MA && iUserDispMode != ENone)
+ {
+ TInt red = TUint8(pixelClr >> 16);
+ TInt green = TUint8(pixelClr >> 8);
+ TInt blue = TUint8(pixelClr);
+ CDrawBitmap::MapColorToUserDisplayMode(red,green,blue);
+ pixelClr = (pixelClr&0xff000000) | (red << 16) | (green << 8) | blue;
+ }
+ *pixelPtr = pixelClr;
+ }
+ pixelPtr += pixelPtrInc;
+ aRgbBuffer += 4;
+ aMaskBuffer++;
+ }
+ }
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::WriteRgbAlphaMulti(TInt aX,TInt aY,TInt aLength,TRgb aColor,const TUint8* aMaskBuffer)
+ {
+ DeOrientate(aX,aY);
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+ const TInt pixelPtrInc = PixelAddressIncrement();
+ const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
+
+ TUint32 srcColor = aColor.Internal();
+ if (iShadowMode)
+ Shadow(srcColor);
+
+ const TInt red = (srcColor & 0x00ff0000) >> 16;
+ const TInt green = (srcColor & 0x0000ff00) >> 8;
+ const TInt blue = srcColor & 0x000000ff;
+ const TInt alpha = srcColor >> 24;
+
+ if (alpha == 255)
+ {
+ // the most common case
+ // source is opaque, so we simply blend it using the mask
+ while (aMaskBuffer < maskBufferPtrLimit)
+ {
+
+ *pixelPtr = OptimizedBlend32A(*pixelPtr, srcColor, *aMaskBuffer);
+
+ pixelPtr += pixelPtrInc;
+ aMaskBuffer++;
+ }
+ }
+ else
+ {
+ // pen is semi-transparent, so we must blend using both the mask and pen alpha
+ while (aMaskBuffer < maskBufferPtrLimit)
+ {
+ TUint8* componentPtr = reinterpret_cast <TUint8*> (pixelPtr);
+ const TUint32 srcAlpha = alpha * aMaskBuffer[0];
+ const TUint32 srcMult = srcAlpha * 255;
+ const TUint32 destMult = (255*255 - srcAlpha) * componentPtr[3];
+ componentPtr[0] = TUint8(((blue * srcMult) + (componentPtr[0] * destMult)) / (255*255*255));
+ componentPtr[1] = TUint8(((green * srcMult) + (componentPtr[1] * destMult)) / (255*255*255));
+ componentPtr[2] = TUint8(((red * srcMult) + (componentPtr[2] * destMult)) / (255*255*255));
+ componentPtr[3] = TUint8((srcMult + destMult) / (255*255));
+ // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
+
+ pixelPtr += pixelPtrInc;
+ aMaskBuffer++;
+ }
+ }
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::WriteRgb(TInt aX,TInt aY,TRgb aColor)
+ {
+ const TInt sourceAlpha = aColor.Alpha();
+
+ if(sourceAlpha==255)
+ {
+ TUint32* componentPtr = PixelAddress(aX,aY);
+ *componentPtr=aColor.Internal();
+ }
+ else if (sourceAlpha==0)
+ {
+ return;
+ }
+ else
+ {
+ TUint8* componentPtr = reinterpret_cast <TUint8*> (PixelAddress(aX,aY));
+ const TUint32 srcMult = sourceAlpha * 255;
+ const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
+ componentPtr[0] = TUint8(((aColor.Blue() * srcMult) + (componentPtr[0] * destMult)) / (255*255));
+ componentPtr[1] = TUint8(((aColor.Green() * srcMult) + (componentPtr[1] * destMult)) / (255*255));
+ componentPtr[2] = TUint8(((aColor.Red() * srcMult) + (componentPtr[2] * destMult)) / (255*255));
+ componentPtr[3] = TUint8((srcMult + destMult) / 255);
+ // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
+ }
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::WriteBinary(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,TInt aHeight,TRgb aColor)
+ {
+ const TInt sourceAlpha = aColor.Alpha();
+ if (sourceAlpha==255)
+ {
+ CDrawThirtyTwoBppBitmapCommon::WriteBinary(aX,aY,aBuffer,aLength,aHeight,aColor);
+ return;
+ }
+ if (sourceAlpha==0)
+ return;
+
+ DeOrientate(aX,aY);
+
+ TInt pixelInc;
+ TInt rowInc;
+
+ switch(iOrientation)
+ {
+ case EOrientationNormal:
+ {
+ pixelInc = 1;
+ rowInc = iScanLineWords;
+ break;
+ }
+ case EOrientationRotated90:
+ {
+ pixelInc = iScanLineWords;
+ rowInc = -1;
+ break;
+ }
+ case EOrientationRotated180:
+ {
+ pixelInc = -1;
+ rowInc = -iScanLineWords;
+ break;
+ }
+ default: // EOrientationRotated270
+ {
+ pixelInc = -iScanLineWords;
+ rowInc = 1;
+ }
+ }
+
+ const TUint32* dataLimit = aBuffer + aHeight;
+ const TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
+
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+
+ const TInt sourceRed = aColor.Red();
+ const TInt sourceGreen = aColor.Green();
+ const TInt sourceBlue = aColor.Blue();
+
+ while (aBuffer < dataLimit)
+ {
+ TUint32 dataWord = *aBuffer++;
+ TUint32 dataMask = 1;
+ TUint32* tempPixelPtr = pixelPtr;
+
+ while (dataMask != dataMaskLimit)
+ {
+ if(dataWord & dataMask)
+ {
+ TUint8* componentPtr = reinterpret_cast <TUint8*> (tempPixelPtr);
+ const TUint32 srcMult = sourceAlpha * 255;
+ const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
+ componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
+ componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
+ componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
+ componentPtr[3] = TUint8((srcMult + destMult) / 255);
+ // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
+ }
+
+ tempPixelPtr += pixelInc;
+ dataMask <<= 1;
+ }
+
+ pixelPtr += rowInc;
+ }
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aBuffer,TInt aHeight,TRgb aColor,TBool aUp)
+ {
+ const TInt sourceAlpha = aColor.Alpha();
+ if (sourceAlpha==255)
+ {
+ CDrawThirtyTwoBppBitmapCommon::WriteBinaryLineVertical(aX,aY,aBuffer,aHeight,aColor,aUp);
+ return;
+ }
+ if (sourceAlpha==0)
+ return;
+
+ DeOrientate(aX,aY);
+
+ TInt scanlineWordLength;
+
+ switch(iOrientation)
+ {
+ case EOrientationNormal:
+ scanlineWordLength = iScanLineWords;
+ break;
+ case EOrientationRotated90:
+ scanlineWordLength = -1;
+ break;
+ case EOrientationRotated180:
+ scanlineWordLength = -iScanLineWords;
+ break;
+ default: // EOrientationRotated270
+ scanlineWordLength = 1;
+ }
+
+ if (aUp)
+ scanlineWordLength = -scanlineWordLength;
+
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+ const TUint32* pixelPtrLimit = pixelPtr + (aHeight * scanlineWordLength);
+ TUint32 dataWord = *aBuffer;
+ TUint32 dataMask = 1;
+
+ const TInt sourceRed = aColor.Red();
+ const TInt sourceGreen = aColor.Green();
+ const TInt sourceBlue = aColor.Blue();
+
+ while(pixelPtr != pixelPtrLimit)
+ {
+ if(!dataMask)
+ {
+ dataMask = 1;
+ aBuffer++;
+ dataWord = *aBuffer;
+ }
+
+ if(dataWord & dataMask)
+ {
+ TUint8* componentPtr = reinterpret_cast <TUint8*> (pixelPtr);
+ const TUint32 srcMult = sourceAlpha * 255;
+ const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
+ componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
+ componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
+ componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
+ componentPtr[3] = TUint8((srcMult + destMult) / 255);
+ // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
+ }
+
+ dataMask <<= 1;
+ pixelPtr += scanlineWordLength;
+ }
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::MapBufferToUserDisplayMode(TInt aLength,TUint32* aBuffer)
+ {
+ const TUint32* bufferLimit = aBuffer + aLength;
+ TRgb color;
+
+ switch (iUserDispMode)
+ {
+ case EGray2:
+ while (aBuffer < bufferLimit)
+ {
+ color = TRgb::_Color16MA(*aBuffer);
+ color = TRgb::_Gray2(color._Gray2());
+ *aBuffer++ = color._Color16MA();
+ }
+ break;
+ case EGray4:
+ while (aBuffer < bufferLimit)
+ {
+ color = TRgb::_Color16MA(*aBuffer);
+ color = TRgb::_Gray4(color._Gray4());
+ *aBuffer++ = color._Color16MA();
+ }
+ break;
+ case EGray16:
+ while (aBuffer < bufferLimit)
+ {
+ color = TRgb::_Color16MA(*aBuffer);
+ color = TRgb::_Gray16(color._Gray16());
+ *aBuffer++ = color._Color16MA();
+ }
+ break;
+ case EGray256:
+ while (aBuffer < bufferLimit)
+ {
+ color = TRgb::_Color16MA(*aBuffer);
+ color = TRgb::_Gray256(color._Gray256());
+ *aBuffer++ = color._Color16MA();
+ }
+ break;
+ case EColor16:
+ while (aBuffer < bufferLimit)
+ {
+ color = TRgb::_Color16MA(*aBuffer);
+ color = TRgb::Color16(color.Color16());
+ *aBuffer++ = color._Color16MA();
+ }
+ break;
+ case EColor256:
+ while (aBuffer < bufferLimit)
+ {
+ color = TRgb::_Color16MA(*aBuffer);
+ color = TRgb::Color256(color.Color256());
+ *aBuffer++ = color._Color16MA();
+ }
+ break;
+ case EColor4K:
+ while (aBuffer < bufferLimit)
+ {
+ color = TRgb::_Color16MA(*aBuffer);
+ color = TRgb::_Color4K(color._Color4K());
+ *aBuffer++ = color._Color16MA();
+ }
+ break;
+ case EColor64K:
+ while (aBuffer < bufferLimit)
+ {
+ color = TRgb::_Color16MA(*aBuffer);
+ color = TRgb::_Color64K(color._Color64K());
+ *aBuffer++ = color._Color16MA();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::BlendRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
+ {
+ const TInt sourceAlpha = aColor.Alpha();
+ if (sourceAlpha==255)// opaque
+ {
+ WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
+ return;
+ }
+ if (sourceAlpha==0)// transparent
+ return;
+
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+ TUint32* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineWords);
+ TUint32* pixelPtrLimit = pixelPtr + aLength;
+
+ const TInt sourceRed = aColor.Red();
+ const TInt sourceGreen = aColor.Green();
+ const TInt sourceBlue = aColor.Blue();
+ TUint srcValue = aColor._Color16MA();
+ while (pixelPtr < pixelRowPtrLimit)
+ {
+ for (TUint32* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr++)
+ {
+ // check that the alpha value is not 0xFF
+ if((*tempPixelPtr & 0xFF000000) ^ 0xFF000000)
+ {
+ TUint8* componentPtr = reinterpret_cast <TUint8*> (tempPixelPtr);
+ const TUint32 srcMult = sourceAlpha * 255;
+ const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
+ componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
+ componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
+ componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
+ componentPtr[3] = TUint8((srcMult + destMult) / 255);
+ }
+ else
+ {
+ AlphaBlendPixelToDest(srcValue, (TUint8)sourceAlpha, tempPixelPtr);
+ }
+
+ // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
+ }
+
+ pixelPtr += iScanLineWords;
+ pixelPtrLimit += iScanLineWords;
+ }
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::BlendLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
+ {
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+
+ const TUint32* bufferPtrLimit = aBuffer + aLength;
+ const TInt pixelPtrInc = (iOrientation == EOrientationNormal) ? 1 : PixelAddressIncrement();
+
+ while (aBuffer < bufferPtrLimit)
+ {
+ *pixelPtr = OptimizedBlend32A(*pixelPtr, *aBuffer, (*aBuffer)>>24);
+
+ aBuffer++;
+ pixelPtr += pixelPtrInc;
+ }
+ }
+
+TRgb CDrawThirtyTwoBppBitmapAlpha::RgbColor(TUint32 aColor) const
+ {
+ return TRgb::_Color16MA(aColor);
+ }
+
+TUint32 CDrawThirtyTwoBppBitmapAlpha::Color(const TRgb& aColor)
+ {
+ return aColor._Color16MA();
+ }
+
+void CDrawThirtyTwoBppBitmapAlpha::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));
+
+ TUint32* pixelPtr = PixelAddress(rect.iTl.iX,rect.iTl.iY);
+ TUint32* pixelRowPtrLimit = pixelPtr + (rect.Height() * iScanLineWords);
+
+ TUint32* pixelRowPtr = pixelPtr;
+ TUint32* pixelPtrLimit = pixelPtr + rect.Width();
+
+ if (iShadowMode & EFade)
+ {
+#if !defined(SYMBIAN_USE_FAST_FADING)
+ const TInt wordFadeMapOffset = ((iFadeMapOffset & 0xff) << 16) | (iFadeMapOffset & 0xff);
+#endif
+ while (pixelRowPtr < pixelRowPtrLimit)
+ {
+ TUint32* tempPixelPtr = pixelRowPtr;
+
+ while (tempPixelPtr < pixelPtrLimit)
+ {
+ const TUint32 color = *tempPixelPtr;
+#if defined(SYMBIAN_USE_FAST_FADING)
+ *tempPixelPtr++ = (color & 0xff000000) | ((((color & 0x00ffffff) >> 1) & ~0x00808080) + (SYMBIAN_USE_FAST_FADING));
+#else
+ const TInt rb = ((((color & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
+ const TInt g = ((((color & 0x0000ff00) * iFadeMapFactor) >> 16) + iFadeMapOffset) << 8;
+ *tempPixelPtr++ = (color & 0xff000000) | rb | g;
+#endif
+ }
+
+ pixelRowPtr += iScanLineWords;
+ pixelPtrLimit += iScanLineWords;
+ }
+ }
+
+ if (iShadowMode & EShadow)
+ {
+ pixelRowPtr = pixelPtr;
+ pixelPtrLimit = pixelPtr + rect.Width();
+
+ while (pixelRowPtr < pixelRowPtrLimit)
+ {
+ TUint32* tempPixelPtr = pixelRowPtr;
+
+ while (tempPixelPtr < pixelPtrLimit)
+ {
+ const TUint32 color = *tempPixelPtr;
+ const TInt r = (color & 0x00c00000) ? ((color & 0x00ff0000)-0x00400000) : 0;
+ const TInt g = (color & 0x0000c000) ? ((color & 0x0000ff00)-0x00004000) : 0;
+ const TInt b = (color & 0x000000c0) ? ((color & 0x000000ff)-0x00000040) : 0;
+ *tempPixelPtr++ = (color & 0xff000000) | r | g | b;
+ }
+
+ pixelRowPtr += iScanLineWords;
+ pixelPtrLimit += iScanLineWords;
+ }
+ }
+ }
+
+TInt CDrawThirtyTwoBppBitmapAlpha::WriteRgbOutlineAndShadow(TInt aX, TInt aY, const TInt aLength,
+ TUint32 aOutlinePenColor, TUint32 aShadowColor,
+ TUint32 aFillColor, const TUint8* aDataBuffer)
+ {
+ DeOrientate(aX,aY);
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+ const TInt pixelPtrInc = PixelAddressIncrement();
+ const TUint8* dataBufferPtrLimit = aDataBuffer + aLength;
+ TInt blendedRedColor;
+ TInt blendedGreenColor;
+ TInt blendedBlueColor;
+ TUint8 index = 0;
+ TUint32 finalColor;
+
+ //Get red color. Equivalent to TRgb::Red()
+ const TInt redOutlinePenColor = (aOutlinePenColor & 0xff0000) >> 16;
+ const TInt redShadowColor = (aShadowColor & 0xff0000) >> 16;
+ const TInt redFillColor = (aFillColor & 0xff0000) >> 16;
+
+ //Get green color. Equivalent to TRgb::Green()
+ const TInt greenOutlinePenColor = (aOutlinePenColor & 0xff00) >> 8;
+ const TInt greenShadowColor = (aShadowColor & 0xff00) >> 8;
+ const TInt greenFillColor = (aFillColor & 0xff00) >> 8;
+
+ //Get blue color. Equivalent to TRgb::Blue()
+ const TInt blueOutlinePenColor = aOutlinePenColor & 0xff;
+ const TInt blueShadowColor = aShadowColor & 0xff;
+ const TInt blueFillColor = aFillColor & 0xff;
+ 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])
+ {
+ //Use fill colour to draw
+ finalColor = aFillColor;
+ }
+ else if (255 == FourColorBlendLookup[index][KShadowColorIndex])
+ {
+ //Use shadow colour to draw
+ finalColor = aShadowColor;
+ }
+ else if (255 == FourColorBlendLookup[index][KOutlineColorIndex])
+ {
+ //Use outline colour to draw
+ finalColor = aOutlinePenColor;
+ }
+ else
+ {
+ const TUint32 backgroundColor = *pixelPtr;
+
+ blendedRedColor = (redOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] +
+ redShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
+ redFillColor * FourColorBlendLookup[index][KFillColorIndex] +
+ ((backgroundColor & 0xff0000) >> 16) * FourColorBlendLookup[index][KBackgroundColorIndex]) >> 8;
+
+ blendedGreenColor = (greenOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] +
+ greenShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
+ greenFillColor * FourColorBlendLookup[index][KFillColorIndex] +
+ ((backgroundColor & 0xff00) >> 8) * FourColorBlendLookup[index][KBackgroundColorIndex]) >> 8;
+
+ blendedBlueColor = (blueOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] +
+ blueShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
+ blueFillColor * FourColorBlendLookup[index][KFillColorIndex] +
+ (backgroundColor & 0xff) * FourColorBlendLookup[index][KBackgroundColorIndex]) >> 8;
+
+ finalColor = (blendedRedColor << 16) | (blendedGreenColor << 8) | blendedBlueColor | 0xff000000;
+ }
+ *pixelPtr = OptimizedBlend32A(*pixelPtr, finalColor, alpha);
+ pixelPtr += pixelPtrInc;
+ }
+ return KErrNone;
+ }