--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/screendriver/sbit/BMDRAW32PMA.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,806 @@
+// Copyright (c) 2006-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 <graphics/lookuptable.h>
+#include <graphics/blendingalgorithms.h>
+
+/*
+Does the same conversion as NonPMA2PMAPixel, but leaves the values in the RB and G uint32 values
+ready for use in the blending algorithm. Also assumes alphas of 0 or 0xFF have already been
+stripped out as special cases.
+*/
+FORCEINLINE void NonPMA2PMAPixelRBG(TUint32 aPixel, TUint32 &aSrcRB, TUint32 &aSrcG, TUint32 &aMask)
+ {
+ TUint32 alpha=(aPixel >> 24);
+ aMask = 0x0100 - alpha; // for use in PMABlend_fromRBandG
+ TUint32 tap1=alpha+1;
+ aSrcRB = (aPixel & KRBMask) * tap1;
+ aSrcRB >>= 8;
+ aSrcRB &= KRBMask;
+ aSrcG = (aPixel&0xFF000000) | (((aPixel & KGMask)>>8) * tap1) & KAGMask;
+ }
+
+/*
+Uses same algorithm as PMABlend_noChecksInplace, but optimised for use with NonPMA2PMAPixelRBG where
+source values are pre-split into RB and G components ready for use in blend
+*/
+FORCEINLINE void PMABlend_fromRBandG(TUint32& aDest_io, const TUint32 aSrcRB, const TUint32 aSrcG, const TUint8 aMask)
+ {
+ TUint32 dst_ag = (aDest_io & KAGMask) >> 8;
+ aDest_io = aDest_io & KRBMask;
+ aDest_io = (aSrcRB + ((aMask * aDest_io) >> 8)) & KRBMask;
+ aDest_io |= (aSrcG + (aMask * dst_ag)) & KAGMask;
+ }
+
+/*
+Takes a non-PM source colour and an alpha value
+First pre-multiplies aSrcPixel with aAlpha
+Then blends it into aDestIo using the same alpha value.
+*/
+FORCEINLINE void PMABlend_FromNonPmAndAlpha(TUint32& aDest_io, const TUint32& aSrcPixel, TUint32 aAlpha)
+ {
+ TUint32 tap1=aAlpha+1;
+ TUint32 srcRB = (aSrcPixel & KRBMask) * tap1;
+ srcRB=(srcRB>>8) & KRBMask;
+ TUint32 srcAG = (aSrcPixel & KGMask ) * tap1;
+ srcAG=(srcAG>>8) & KGMask;
+ srcAG|=aAlpha<<24;
+
+ TUint32 dst_ag = (aDest_io & KAGMask) >> 8;
+ TUint32 dst_rb = aDest_io & KRBMask;
+ const TUint32 mask = 0x0100 - aAlpha;
+ aDest_io = (srcRB + ((mask*dst_rb) >> 8)) & KRBMask;
+ aDest_io |= (srcAG + mask*dst_ag) & KAGMask;
+ }
+
+// Same as NonPMA2PMAPixel, but for use where checks for alpha of 0 or 0xFF have already been done
+FORCEINLINE TUint32 NonPMA2PMAPixelNoCheck(TUint32 aPixel)
+ {
+ TUint32 tap1=(aPixel>>24)+1;
+ TUint32 scaledRB = (aPixel & KRBMask) * tap1;
+ TUint32 scaledG = (aPixel & KGMask ) * tap1;
+ return (aPixel & 0xff000000) | ((scaledRB>>8) & KRBMask) | ((scaledG>>8)& KGMask);
+ }
+
+/**
+Composite mask application
+where AlphaComposite = AlphaColor * AlphaMask / 255.
+@param aColor - non-premltiplied color with alpha
+@param aMask - the mask value. (0 to 255).
+@return the color with alpha combined from color and mask (combination
+operator used is scaled multiplication).
+*/
+FORCEINLINE TUint32 CompMask(TUint32 aColor, TUint8 aMask)
+ {
+ // if the mask is FF the colour will be fully opaque and can be immediatly returned
+ if (aMask == 0xff)
+ return aColor;
+
+ TUint32 cAlpha = (aMask+1) * (aColor >> 24);
+ return ((aColor & 0x00ffffff) | ((cAlpha <<16) & 0xff000000));
+ }
+
+TInt CDrawThirtyTwoBppBitmapAlphaPM::Construct(TSize aSize)
+ {
+ return Construct(aSize, aSize.iWidth << 2);
+ }
+
+TInt CDrawThirtyTwoBppBitmapAlphaPM::Construct(TSize aSize, TInt aStride)
+ {
+ iDispMode = EColor16MAP;
+ return CDrawThirtyTwoBppBitmapCommon::Construct(aSize, aStride);
+ }
+
+/**
+MAlphaBlend::WriteRgbAlphaLine() implementation.
+Blends the supplied buffer of TRgb format data (ARGB), and the mask, to the destination
+which is specified by the pixel positions aX, aY and length.
+@param aX The starting position on the x-axis for the destination pixel.
+@param aY The starting position on the y-axis for the destination pixel.
+@param aRgbBuffer The RGB source data buffer. This is assumed to be bit aligned 32 bit non-premultiplied data
+@param aMaskBuffer The masking data. The mask buffer and the source alpha values are multiplied together to
+ generate the alpha used for blending to the destination.
+@param aShadowing The shadowing flag. Indicates when and how to apply shadowing.
+@param aDrawMode The mode for rendering the source image to the destination.
+ Currently supports EWriteAlpha and EPenmode.
+
+@see MAlphaBlend::WriteRgbAlphaLine()
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::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 TUint16* normTable = PtrTo16BitNormalisationTable();
+ TRgb tmp;
+ 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 EColor16MAP
+ if(!(iShadowMode & (EFade | EShadow)) && (iUserDispMode ==EColor16MAP || iUserDispMode == ENone))
+ {
+ while (aMaskBuffer < maskBufferPtrLimit)
+ {
+ if (*aMaskBuffer)
+ {
+ TUint32 srcData = *((TUint32*)aRgbBuffer);
+ if ((aDrawMode == CGraphicsContext::EDrawModeWriteAlpha) && (*aMaskBuffer == 0xFF))
+ {
+ // Write the source straight through to the target, otherwise
+ // blend. This relies on the fact that EDrawModeWriteAlpha can only
+ // be used with masks that contain only black or white.
+ Convert2PMA(srcData);
+ *pixelPtr = srcData;
+ }
+ else
+ {
+ //blend alpha value in source with the mask value.
+ srcData = CompMask(srcData, *aMaskBuffer);
+ //pre-multiply, inplace.
+ Convert2PMA(srcData);
+ PMAInplaceBlend(*pixelPtr, srcData);
+ }
+ }
+ pixelPtr += pixelPtrInc;
+ aRgbBuffer += 4;
+ aMaskBuffer++;
+ }
+ }
+ else
+ {
+ while (aMaskBuffer < maskBufferPtrLimit)
+ {
+ TUint32 srcColor = *((TUint32*)(aRgbBuffer));
+ if(*aMaskBuffer)
+ {
+ if(aShadowing == MAlphaBlend::EShdwBefore)
+ {
+ // src color in non-premultiplied.
+ Shadow(*(TRgb*)&srcColor);
+ }
+ TUint32 srcData;
+ if ((aDrawMode == CGraphicsContext::EDrawModeWriteAlpha) && (*aMaskBuffer == 0xFF))
+ {
+ Convert2PMA(srcColor);
+ srcData = srcColor;
+ }
+ else
+ {
+ //blend alpha value in source with the mask value.
+ srcData = CompMask(srcColor, *aMaskBuffer);
+ //pre-multiply, inplace.
+ Convert2PMA(srcData);
+ srcData = PMAPixelBlend(*pixelPtr, srcData);
+ }
+
+ if(aShadowing == MAlphaBlend::EShdwAfter)
+ {
+ // shadow is done in PMA mode.
+ Shadow(srcData);
+ }
+ if(iUserDispMode !=EColor16MAP && iUserDispMode != ENone)
+ {
+ tmp.SetInternal(PMA2NonPMAPixel(srcData, normTable));
+ CDrawThirtyTwoBppBitmapCommon::MapColorToUserDisplayMode(tmp);
+ srcData = tmp.Internal();
+ Convert2PMA(srcData);
+ }
+ *pixelPtr = srcData;
+ }
+ pixelPtr += pixelPtrInc;
+ aRgbBuffer += 4;
+ aMaskBuffer++;
+ }
+ }
+ }
+
+/**
+This assumes that the pen color (aColor) alpha information is to be blended with
+the alpha provided by the mask buffer.
+If pen is opaque, the mask is used as transparency information to be used.
+If pen is semi-transparent, the mask is contructed by calculating the resulting alpha
+by multiplying the mask with the alpha information of the pen color.
+@see CFbsDrawDevice::WriteRgbAlphaMulti
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::WriteRgbAlphaMulti(TInt aX,TInt aY,TInt aLength,TRgb aColor,const TUint8* aMaskBuffer)
+ {
+ TUint32 srcAlpha = aColor.Alpha();
+ if (srcAlpha==0 || aLength<=0)
+ return;
+ DeOrientate(aX,aY);
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+ const TInt pixelPtrInc = PixelAddressIncrement();
+ const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
+ if (iShadowMode)
+ CDrawThirtyTwoBppBitmapCommon::Shadow(aColor);
+ // pre-multiply the color.
+ const TUint32 srcColor = aColor.Internal();
+ if (srcAlpha == 255)
+ { // source (pen) is opaque, so we simply blend it using the mask
+ // little trick to make main loop more optimised, having 'pixelPtr += pixelPtrInc' at the top
+ // of the loop makes the compiler generate better code without extra jumps to reach the
+ // 'pixelPtr += pixelPtrInc' line.
+ // We also need to do the FOREVER loop with a break when aMaskBuffer==maskBufferPtrLimit or
+ // else the compiler puts the test at the end and extra jumps are required to reach it.
+ pixelPtr -= pixelPtrInc;
+ FOREVER
+ {
+ pixelPtr += pixelPtrInc;
+ if (aMaskBuffer==maskBufferPtrLimit)
+ break;
+ const TUint maskAlpha=*aMaskBuffer++;
+ if (maskAlpha==0)
+ { // Most pixels in text are blank, so this is the most important route to optimise
+ continue;
+ }
+ else if (maskAlpha==0xFF)
+ { // Second most important are fully opaque pixels
+ *pixelPtr=srcColor;
+ continue;
+ }
+ TUint32 maskColor = NonPMA2PMAPixelNoCheck((srcColor&~0xFF000000) | ((TUint32)maskAlpha << 24));
+ PMAInplaceBlend(*pixelPtr, maskColor);
+ }
+ }
+ else if(srcAlpha > 0)
+ {
+ // pen is semi-transparent, so we must blend using both the mask and pen alpha
+ // pre calculate ffMaskColor optimised for common case where aMaskBuffer contains 0xFF
+ const TUint32 ffMaskColor=NonPMA2PMAPixelNoCheck(srcColor);
+ const TUint32 noAlphaSrcColor=srcColor&0xFFFFFF;
+ while (aMaskBuffer < maskBufferPtrLimit)
+ {
+ const TUint maskAlpha=*aMaskBuffer;
+ if (maskAlpha)
+ {
+ if (maskAlpha==0xFF)
+ PMABlend_noChecksInplace(*pixelPtr, ffMaskColor, srcAlpha);
+ else
+ {
+ TUint32 mixedAlpha = ((maskAlpha+1) * srcAlpha)>>8;
+ PMABlend_FromNonPmAndAlpha(*pixelPtr, noAlphaSrcColor, mixedAlpha);
+ }
+ }
+ pixelPtr += pixelPtrInc;
+ aMaskBuffer++;
+ }
+ }
+ }
+
+/**
+@see CFbsDrawDevice::WriteRgb
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::WriteRgb(TInt aX,TInt aY,TRgb aColor)
+ {
+ TUint32 srcColor = NonPMA2PMAPixel(aColor.Internal());
+ TUint32* pixelPtr = PixelAddress(aX,aY);
+ PMAInplaceBlend(*pixelPtr, srcColor);
+ }
+
+/**
+@see CFbsDrawDevice::WriteBinary
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::WriteBinary(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,TInt aHeight,TRgb aColor)
+ {
+ const TUint32 colorInternal=aColor.Internal();
+ const TUint8 srcAlpha = colorInternal >> 24;
+ if (srcAlpha==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);
+ if (srcAlpha==0xFF)
+ {
+ while (aBuffer < dataLimit)
+ {
+ TUint32 dataWord = *aBuffer++;
+ TUint32 dataMask = 1;
+ TUint32* tempPixelPtr = pixelPtr;
+ while (dataMask != dataMaskLimit)
+ {
+ if(dataWord & dataMask)
+ {
+ *tempPixelPtr=colorInternal;
+ }
+
+ tempPixelPtr += pixelInc;
+ dataMask <<= 1;
+ }
+
+ pixelPtr += rowInc;
+ }
+ }
+ else
+ {
+ TUint32 src_rb;
+ TUint32 src_g;
+ TUint32 mask;
+ //pre-multiply the src color, before blending.
+ NonPMA2PMAPixelRBG(colorInternal,src_rb,src_g,mask);
+ while (aBuffer < dataLimit)
+ {
+ TUint32 dataWord = *aBuffer++;
+ TUint32 dataMask = 1;
+ TUint32* tempPixelPtr = pixelPtr;
+ while (dataMask != dataMaskLimit)
+ {
+ if(dataWord & dataMask)
+ {
+ PMABlend_fromRBandG(*tempPixelPtr, src_rb, src_g, mask);
+ }
+
+ tempPixelPtr += pixelInc;
+ dataMask <<= 1;
+ }
+
+ pixelPtr += rowInc;
+ }
+ }
+ }
+
+/**
+@see CFbsDrawDevice::WriteBinaryLineVertical
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aBuffer,TInt aHeight,TRgb aColor,TBool aUp)
+ {
+ const TUint32 colorInternal=aColor.Internal();
+ const TInt sourceAlpha = colorInternal>>24;
+ 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;
+
+ if (sourceAlpha==0xFF)
+ {
+ while(pixelPtr != pixelPtrLimit)
+ {
+ if(!dataMask)
+ {
+ dataMask = 1;
+ aBuffer++;
+ dataWord = *aBuffer;
+ }
+
+ if(dataWord & dataMask)
+ {
+ *pixelPtr = colorInternal;
+ }
+ dataMask <<= 1;
+ pixelPtr += scanlineWordLength;
+ }
+ }
+ else
+ {
+ TUint32 src_rb;
+ TUint32 src_g;
+ TUint32 mask;
+ //pre-multiply the src color, before blending.
+ NonPMA2PMAPixelRBG(colorInternal,src_rb,src_g,mask);
+ while(pixelPtr != pixelPtrLimit)
+ {
+ if(!dataMask)
+ {
+ dataMask = 1;
+ aBuffer++;
+ dataWord = *aBuffer;
+ }
+
+ if(dataWord & dataMask)
+ {
+ PMABlend_fromRBandG(*pixelPtr, src_rb, src_g, mask);
+ }
+ dataMask <<= 1;
+ pixelPtr += scanlineWordLength;
+ }
+ }
+ }
+
+/**
+@see CFbsDrawDevice::BlendRgbMulti
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::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;
+
+ TUint32 srcValue = NonPMA2PMAPixel(aColor.Internal());
+ TUint32 src_c = srcValue & KRBMask;
+ TUint32 src_g = (srcValue & KAGMask)>>8;
+ const TUint32 mask = 0x0100 - sourceAlpha;
+ while (pixelPtr < pixelRowPtrLimit)
+ {
+ for (TUint32* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr++)
+ {
+ const TUint32 dst = *tempPixelPtr;
+ TUint32 dst_c = dst & KRBMask;
+ dst_c = (src_c + ((mask * dst_c)>>8)) & KRBMask;
+ const TUint32 dst_ag = (dst & KAGMask)>>8;
+ dst_c |= ((src_g + ((mask * dst_ag)>>8)) & KRBMask)<<8;
+ *tempPixelPtr=dst_c;
+ }
+ pixelPtr += iScanLineWords;
+ pixelPtrLimit += iScanLineWords;
+ }
+ }
+
+/**
+@see CFbsDrawDevice::BlendLine
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::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)
+ {
+ PMAInplaceBlend(*pixelPtr, *aBuffer);
+ aBuffer++;
+ pixelPtr += pixelPtrInc;
+ }
+ }
+/**
+@see CFbsDrawDevice::ShadowArea
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::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)
+ {
+ while (pixelRowPtr < pixelRowPtrLimit)
+ {
+ TUint32* tempPixelPtr = pixelRowPtr;
+
+ while (tempPixelPtr < pixelPtrLimit)
+ {
+ const TUint32 color = *tempPixelPtr;
+#if defined(SYMBIAN_USE_FAST_FADING)
+ const TUint32 fast_fade_offset = NonPMA2PMAPixel((color & 0xff000000) | SYMBIAN_USE_FAST_FADING) & 0x00ffffff;
+ *tempPixelPtr++ = (color & 0xff000000) | ((((color & 0x00ffffff) >> 1) & ~0x00808080) + fast_fade_offset);
+#else
+ const TInt alpha = (color >> 24) + 1;
+ const TUint32 fadeMapOffset = ((alpha * iFadeMapOffset) >> 8) & 0xff;
+ const TUint32 wordFadeMapOffset = ((fadeMapOffset) << 16) | (fadeMapOffset);
+ const TUint32 rb = ((((color & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
+ const TUint32 g = ((((color & 0x0000ff00) * iFadeMapFactor) >> 16) + fadeMapOffset) << 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 alpha = (color >> 24) + 1;
+ const TInt uLimit = ((0x40) * alpha) >> 8;
+ TInt r = (color >> 16) & 0xff;
+ r = (r > uLimit) ? (r-uLimit) : 0;
+ TInt g = (color >> 8) & 0xff;
+ g = (g > uLimit) ? (g - uLimit) : 0;
+ TInt b = color & 0xff;
+ b = (b > uLimit) ? (b - uLimit) : 0;
+ *tempPixelPtr++ = (color & 0xff000000) | (r << 16) | (g << 8) | b;
+ }
+ pixelRowPtr += iScanLineWords;
+ pixelPtrLimit += iScanLineWords;
+ }
+ }
+ }
+
+/**
+@see CFbsDrawDevice::WriteLine
+*/
+void CDrawThirtyTwoBppBitmapAlphaPM::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)
+ {
+#if defined(_DEBUG)
+ // code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
+// RDebug::Printf("Premultiplied alpha mode invert pen behaviour not defined / implemented");
+#endif
+ // no-operation
+ }
+ if(aDrawMode&CGraphicsContext::EPenmode)
+ {
+ BlendLine(aX,aY,aLength,aBuffer);
+ return;
+ }
+ if(aDrawMode&CGraphicsContext::EWriteAlpha)
+ {
+ CDrawThirtyTwoBppBitmapCommon::WriteLine(aX,aY,aLength,aBuffer);
+ return;
+ }
+ if(aDrawMode&CGraphicsContext::EInvertScreen)
+ {
+#if defined(_DEBUG)
+// RDebug::Printf("Premultiplied alpha mode invert screen behaviour not defined / implemented");
+#endif
+ return; //no-operation
+ }
+ if(aDrawMode&CGraphicsContext::EXor)
+ {
+#if defined(_DEBUG)
+ // code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
+// RDebug::Printf("Premultiplied alpha mode XOR operation not defined / implemented");
+#endif
+ return; //no-operation
+ }
+else if(aDrawMode&CGraphicsContext::EAnd)
+ {
+#if defined(_DEBUG)
+ // code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
+// RDebug::Printf("Premultiplied alpha mode AND operation not defined / implemented");
+#endif
+ return; //no-operation
+ }
+ else if(aDrawMode&CGraphicsContext::EOr)
+ {
+#if defined(_DEBUG)
+// RDebug::Printf("Premultiplied alpha mode OR operation not defined / implemented");
+#endif
+ return; //no-operation
+ }
+ }
+
+TRgb CDrawThirtyTwoBppBitmapAlphaPM::RgbColor(TUint32 aColor) const
+ {
+ return TRgb::_Color16MAP(aColor);
+ }
+
+TUint32 CDrawThirtyTwoBppBitmapAlphaPM::Color(const TRgb& aColor)
+ {
+ return aColor._Color16MAP();
+ }
+
+TInt CDrawThirtyTwoBppBitmapAlphaPM::WriteRgbOutlineAndShadow(TInt aX, TInt aY, const TInt aLength,
+ TUint32 aOutlinePenColor, TUint32 aShadowColor,
+ TUint32 aFillColor, const TUint8* aDataBuffer)
+ {
+ const TUint alphaShifted = aOutlinePenColor & 0xff000000;
+ const TUint alpha = alphaShifted>>24;
+ if (alpha==0 || aLength<=0)
+ return KErrNone;
+ 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 TUint16* normTable = PtrTo16BitNormalisationTable();
+
+ // Calculate PMA values for aFillColor & aOutlinePenColor that we can use for fast blending in the simple cases
+ // Don't pre calculate PMA version of aShadowColor as it is presumed not to be used enough to make this worthwhile
+ const TUint32 pmaFillColor = NonPMA2PMAPixel((aFillColor&0x00FFFFFF)|alphaShifted);
+ const TUint32 pmaOutlineColor = NonPMA2PMAPixel(aOutlinePenColor);
+ while (aDataBuffer < dataBufferPtrLimit)
+ {
+ TUint backgroundAlpha;
+ TUint outlineAlpha;
+ TUint shadowAlpha;
+ TUint fillAlpha;
+ index = *aDataBuffer++;
+ backgroundAlpha = FourColorBlendLookup[index][KBackgroundColorIndex];
+ if (backgroundAlpha == 255)
+ {
+ //background colour
+ //No drawing required so move on to next pixel.
+ pixelPtr += pixelPtrInc;
+ continue;
+ }
+ fillAlpha=FourColorBlendLookup[index][KFillColorIndex];
+ if (fillAlpha == 255)
+ {
+ //Use fill colour to draw
+ finalColor = pmaFillColor;
+oneColorBlend:
+ if (alpha==0xFF)
+ *pixelPtr=finalColor;
+ else
+ PMABlend_noChecksInplace(*pixelPtr, finalColor, alpha);
+ pixelPtr += pixelPtrInc;
+ continue;
+ }
+ outlineAlpha = FourColorBlendLookup[index][KOutlineColorIndex];
+ if (outlineAlpha == 255)
+ {
+ //Use outline colour to draw
+ finalColor = pmaOutlineColor;
+ goto oneColorBlend;
+ }
+ shadowAlpha = FourColorBlendLookup[index][KShadowColorIndex];
+ if (shadowAlpha == 255)
+ {
+ //Use shadow colour to draw
+ finalColor = NonPMA2PMAPixel((aShadowColor&0x00FFFFFF)|alphaShifted);
+ goto oneColorBlend;
+ }
+ blendedRedColor = redOutlinePenColor * outlineAlpha +
+ redShadowColor * shadowAlpha +
+ redFillColor * fillAlpha;
+
+ blendedGreenColor = greenOutlinePenColor * outlineAlpha +
+ greenShadowColor * shadowAlpha +
+ greenFillColor * fillAlpha;
+
+ blendedBlueColor = blueOutlinePenColor * outlineAlpha +
+ blueShadowColor * shadowAlpha +
+ blueFillColor * fillAlpha;
+ if (backgroundAlpha)
+ {
+ const TUint32 backgroundColor = PMA2NonPMAPixel(*pixelPtr, normTable);
+ blendedRedColor += ((backgroundColor & 0xff0000) >> 16) * backgroundAlpha;
+ blendedGreenColor += ((backgroundColor & 0xff00) >> 8) * backgroundAlpha;
+ blendedBlueColor += (backgroundColor & 0xff) * backgroundAlpha;
+ }
+ finalColor = ((blendedRedColor&0xFF00)<<8) | (blendedGreenColor&0xFF00) | (blendedBlueColor>>8);
+
+ if (alpha==0xFF)
+ *pixelPtr=finalColor|0xFF000000;
+ else
+ {
+ //pre-multiply, inplace.
+ finalColor = NonPMA2PMAPixel(finalColor|alphaShifted);
+ PMABlend_noChecksInplace(*pixelPtr, finalColor, alpha);
+ }
+ pixelPtr += pixelPtrInc;
+ }
+ return KErrNone;
+ }