graphicsdeviceinterface/screendriver/sbit/BMDRAW32PMA.cpp
changeset 0 5d03bc08d59c
child 33 25f95128741d
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "BMDRAW.H"
       
    17 #include <graphics/lookuptable.h>
       
    18 #include <graphics/blendingalgorithms.h>
       
    19 
       
    20 /*
       
    21 Does the same conversion as NonPMA2PMAPixel, but leaves the values in the RB and G uint32 values
       
    22 ready for use in the blending algorithm. Also assumes alphas of 0 or 0xFF have already been
       
    23 stripped out as special cases.
       
    24 */
       
    25 FORCEINLINE void NonPMA2PMAPixelRBG(TUint32 aPixel, TUint32 &aSrcRB, TUint32 &aSrcG, TUint32 &aMask)
       
    26 	{
       
    27 	TUint32 alpha=(aPixel >> 24);
       
    28 	aMask = 0x0100 - alpha;	// for use in PMABlend_fromRBandG
       
    29 	TUint32 tap1=alpha+1;
       
    30 	aSrcRB = (aPixel & KRBMask) * tap1;
       
    31 	aSrcRB >>= 8;
       
    32 	aSrcRB &= KRBMask;
       
    33 	aSrcG = (aPixel&0xFF000000) | (((aPixel & KGMask)>>8) * tap1) & KAGMask;
       
    34 	}
       
    35 
       
    36 /*
       
    37 Uses same algorithm as PMABlend_noChecksInplace, but optimised for use with NonPMA2PMAPixelRBG where
       
    38 source values are pre-split into RB and G components ready for use in blend
       
    39 */
       
    40 FORCEINLINE void PMABlend_fromRBandG(TUint32& aDest_io, const TUint32 aSrcRB, const TUint32 aSrcG, const TUint8 aMask)
       
    41 	{
       
    42 	TUint32 dst_ag = (aDest_io & KAGMask) >> 8;
       
    43 	aDest_io = aDest_io  & KRBMask;
       
    44 	aDest_io = (aSrcRB +  ((aMask * aDest_io) >> 8)) & KRBMask;
       
    45 	aDest_io |= (aSrcG +  (aMask * dst_ag)) & KAGMask;
       
    46 	}
       
    47 
       
    48 /*
       
    49 Takes a non-PM source colour and an alpha value
       
    50 First pre-multiplies aSrcPixel with aAlpha
       
    51 Then blends it into aDestIo using the same alpha value.
       
    52 */
       
    53 FORCEINLINE void PMABlend_FromNonPmAndAlpha(TUint32& aDest_io, const TUint32& aSrcPixel, TUint32 aAlpha)
       
    54 	{
       
    55 	TUint32 tap1=aAlpha+1;
       
    56 	TUint32 srcRB = (aSrcPixel & KRBMask) * tap1;
       
    57 	srcRB=(srcRB>>8) & KRBMask;
       
    58 	TUint32 srcAG = (aSrcPixel & KGMask ) * tap1;
       
    59 	srcAG=(srcAG>>8) & KGMask;
       
    60 	srcAG|=aAlpha<<24;
       
    61 
       
    62 	TUint32 dst_ag = (aDest_io & KAGMask) >> 8;
       
    63 	TUint32 dst_rb = aDest_io & KRBMask;
       
    64 	const TUint32 mask = 0x0100 - aAlpha;
       
    65 	aDest_io = (srcRB +  ((mask*dst_rb) >> 8)) & KRBMask;
       
    66 	aDest_io |= (srcAG + mask*dst_ag) & KAGMask;
       
    67 	}
       
    68 
       
    69 // Same as NonPMA2PMAPixel, but for use where checks for alpha of 0 or 0xFF have already been done
       
    70 FORCEINLINE TUint32 NonPMA2PMAPixelNoCheck(TUint32 aPixel)
       
    71 	{
       
    72 	TUint32 tap1=(aPixel>>24)+1;
       
    73 	TUint32 scaledRB = (aPixel & KRBMask) * tap1;
       
    74 	TUint32 scaledG = (aPixel & KGMask ) * tap1;
       
    75 	return (aPixel & 0xff000000) | ((scaledRB>>8) & KRBMask) | ((scaledG>>8)& KGMask);
       
    76 	}
       
    77 
       
    78 /**
       
    79 Composite mask application
       
    80 where AlphaComposite = AlphaColor * AlphaMask / 255.
       
    81 @param aColor - non-premltiplied color with alpha 
       
    82 @param aMask  - the mask value. (0 to 255).
       
    83 @return the color with alpha combined from color and mask (combination
       
    84 operator used is scaled multiplication).
       
    85 */
       
    86 FORCEINLINE TUint32 CompMask(TUint32 aColor, TUint8 aMask)
       
    87 	{
       
    88 	// if the mask is FF the colour will be fully opaque and can be immediatly returned
       
    89 	if (aMask == 0xff)
       
    90 		return aColor;
       
    91 	
       
    92 	TUint32 cAlpha = (aMask+1) * (aColor >> 24);
       
    93 	return ((aColor & 0x00ffffff) | ((cAlpha <<16) & 0xff000000));
       
    94 	}
       
    95 
       
    96 TInt CDrawThirtyTwoBppBitmapAlphaPM::Construct(TSize aSize)
       
    97 	{
       
    98 	return Construct(aSize, aSize.iWidth << 2);
       
    99 	}
       
   100 
       
   101 TInt CDrawThirtyTwoBppBitmapAlphaPM::Construct(TSize aSize, TInt aStride)
       
   102 	{
       
   103 	iDispMode = EColor16MAP;
       
   104 	return CDrawThirtyTwoBppBitmapCommon::Construct(aSize, aStride);
       
   105 	}
       
   106 
       
   107 /**
       
   108 MAlphaBlend::WriteRgbAlphaLine() implementation.
       
   109 Blends the supplied buffer of TRgb format data (ARGB), and the mask, to the destination
       
   110 which is specified by the pixel positions aX, aY and length.
       
   111 @param aX	The starting position on the x-axis for the destination pixel.
       
   112 @param aY	The starting position on the y-axis for the destination pixel.
       
   113 @param aRgbBuffer	The RGB source data buffer. This is assumed to be bit aligned 32 bit non-premultiplied data
       
   114 @param aMaskBuffer	The masking data. The mask buffer and the source alpha values are multiplied together to
       
   115 					generate the alpha used for blending to the destination.
       
   116 @param aShadowing	The shadowing flag. Indicates when and how to apply shadowing.
       
   117 @param aDrawMode	The mode for rendering the source image to the destination. 
       
   118 					Currently supports EWriteAlpha and EPenmode.
       
   119 
       
   120 @see MAlphaBlend::WriteRgbAlphaLine()
       
   121 */
       
   122 void CDrawThirtyTwoBppBitmapAlphaPM::WriteRgbAlphaLine(TInt aX, TInt aY, TInt aLength,
       
   123                                                   const TUint8* aRgbBuffer,
       
   124                                                   const TUint8* aMaskBuffer,
       
   125                                                   MAlphaBlend::TShadowing aShadowing,
       
   126                                                   CGraphicsContext::TDrawMode aDrawMode)
       
   127     {
       
   128     // precondition for this function is that the aRgbBuffer lies on a word boundary
       
   129     // Assert checks that the pointer is at a word boundary
       
   130     __ASSERT_DEBUG(!(((TUint)aRgbBuffer) & 0x3), Panic(EScreenDriverPanicInvalidPointer));
       
   131 
       
   132 	DeOrientate(aX,aY);
       
   133 	TUint32* pixelPtr = PixelAddress(aX,aY);
       
   134 	const TInt pixelPtrInc = PixelAddressIncrement();
       
   135 	const TUint16* normTable = PtrTo16BitNormalisationTable();
       
   136 	TRgb tmp;
       
   137 	const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
       
   138 	// The purpose of this conditional is to remove if statements from within the loop
       
   139 	// if shadow mode is not enabled and the UserDispMode is none or EColor16MAP
       
   140 	if(!(iShadowMode & (EFade | EShadow)) && (iUserDispMode ==EColor16MAP || iUserDispMode == ENone))
       
   141 		{
       
   142 		while (aMaskBuffer < maskBufferPtrLimit)
       
   143 			{
       
   144 			if (*aMaskBuffer)
       
   145 				{
       
   146 				TUint32 srcData = *((TUint32*)aRgbBuffer);
       
   147 				if ((aDrawMode == CGraphicsContext::EDrawModeWriteAlpha) && (*aMaskBuffer == 0xFF))
       
   148 					{
       
   149 					// Write the source straight through to the target, otherwise
       
   150 					// blend. This relies on the fact that EDrawModeWriteAlpha can only
       
   151 					// be used with masks that contain only black or white.
       
   152 					Convert2PMA(srcData);
       
   153 					*pixelPtr = srcData;
       
   154 					}
       
   155 				else
       
   156 					{
       
   157 					//blend alpha value in source with the mask value.
       
   158 					srcData = CompMask(srcData, *aMaskBuffer);
       
   159 					//pre-multiply, inplace.
       
   160 					Convert2PMA(srcData);
       
   161 					PMAInplaceBlend(*pixelPtr, srcData);
       
   162 					}
       
   163 				}
       
   164 			pixelPtr += pixelPtrInc;
       
   165 			aRgbBuffer += 4;
       
   166 			aMaskBuffer++;
       
   167 			}
       
   168 		}
       
   169 	else
       
   170 		{
       
   171 		while (aMaskBuffer < maskBufferPtrLimit)
       
   172 			{
       
   173 			TUint32 srcColor = *((TUint32*)(aRgbBuffer));
       
   174 			if(*aMaskBuffer)
       
   175 				{
       
   176 				if(aShadowing == MAlphaBlend::EShdwBefore)
       
   177 					{
       
   178 					// src color in non-premultiplied.
       
   179 					Shadow(*(TRgb*)&srcColor);
       
   180 					}
       
   181 				TUint32 srcData;
       
   182 				if ((aDrawMode == CGraphicsContext::EDrawModeWriteAlpha) && (*aMaskBuffer == 0xFF))
       
   183 					{
       
   184 					Convert2PMA(srcColor);
       
   185 					srcData = srcColor;
       
   186 					}
       
   187 				else
       
   188 					{
       
   189 					//blend alpha value in source with the mask value.
       
   190 					srcData = CompMask(srcColor, *aMaskBuffer);
       
   191 					//pre-multiply, inplace.
       
   192 					Convert2PMA(srcData);
       
   193 					srcData = PMAPixelBlend(*pixelPtr, srcData);
       
   194 					}
       
   195 
       
   196 				if(aShadowing == MAlphaBlend::EShdwAfter)
       
   197 					{
       
   198 					// shadow is done in PMA mode.
       
   199 					Shadow(srcData);
       
   200 					}
       
   201 				if(iUserDispMode !=EColor16MAP && iUserDispMode != ENone)
       
   202 					{
       
   203 					tmp.SetInternal(PMA2NonPMAPixel(srcData, normTable));
       
   204 					CDrawThirtyTwoBppBitmapCommon::MapColorToUserDisplayMode(tmp);
       
   205 					srcData = tmp.Internal();
       
   206 					Convert2PMA(srcData);
       
   207 					}
       
   208 				*pixelPtr = srcData;
       
   209 				}
       
   210 			pixelPtr += pixelPtrInc;
       
   211 			aRgbBuffer += 4;
       
   212 			aMaskBuffer++;
       
   213 			}
       
   214 		}
       
   215 	}
       
   216 
       
   217 /**
       
   218 This assumes that the pen color (aColor) alpha information is to be blended with
       
   219 the alpha provided by the mask buffer.
       
   220 If pen is opaque, the mask is used as transparency information to be used.
       
   221 If pen is semi-transparent, the mask is contructed by calculating the resulting alpha
       
   222 by multiplying the mask with the alpha information of the pen color.
       
   223 @see CFbsDrawDevice::WriteRgbAlphaMulti
       
   224 */
       
   225 void CDrawThirtyTwoBppBitmapAlphaPM::WriteRgbAlphaMulti(TInt aX,TInt aY,TInt aLength,TRgb aColor,const TUint8* aMaskBuffer)
       
   226 	{
       
   227 	TUint32 srcAlpha = aColor.Alpha();
       
   228 	if (srcAlpha==0 || aLength<=0)
       
   229 		return;
       
   230 	DeOrientate(aX,aY);
       
   231 	TUint32* pixelPtr = PixelAddress(aX,aY);
       
   232 	const TInt pixelPtrInc = PixelAddressIncrement();
       
   233 	const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
       
   234 	if (iShadowMode)
       
   235 		CDrawThirtyTwoBppBitmapCommon::Shadow(aColor);
       
   236 	// pre-multiply the color.
       
   237 	const TUint32 srcColor = aColor.Internal();
       
   238 	if (srcAlpha == 255)
       
   239 		{ // source (pen) is opaque, so we simply blend it using the mask
       
   240 		// little trick to make main loop more optimised, having 'pixelPtr += pixelPtrInc' at the top 
       
   241 		// of the loop makes the compiler generate better code without extra jumps to reach the
       
   242 		// 'pixelPtr += pixelPtrInc' line.
       
   243 		// We also need to do the FOREVER loop with a break when aMaskBuffer==maskBufferPtrLimit or
       
   244 		// else the compiler puts the test at the end and extra jumps are required to reach it.
       
   245 		pixelPtr -= pixelPtrInc;
       
   246 		FOREVER
       
   247 			{
       
   248 			pixelPtr += pixelPtrInc;
       
   249 			if (aMaskBuffer==maskBufferPtrLimit)
       
   250 				break;
       
   251 			const TUint maskAlpha=*aMaskBuffer++;
       
   252 			if (maskAlpha==0)
       
   253 				{	// Most pixels in text are blank, so this is the most important route to optimise
       
   254 				continue;
       
   255 				}
       
   256 			else if (maskAlpha==0xFF)
       
   257 				{	// Second most important are fully opaque pixels
       
   258 				*pixelPtr=srcColor;
       
   259 				continue;
       
   260 				}
       
   261 			TUint32 maskColor = NonPMA2PMAPixelNoCheck((srcColor&~0xFF000000) | ((TUint32)maskAlpha << 24));
       
   262 			PMAInplaceBlend(*pixelPtr, maskColor);
       
   263 			}
       
   264 		}
       
   265 	else if(srcAlpha > 0)
       
   266 		{
       
   267 		// pen is semi-transparent, so we must blend using both the mask and pen alpha
       
   268 		// pre calculate ffMaskColor optimised for common case where aMaskBuffer contains 0xFF
       
   269 		const TUint32 ffMaskColor=NonPMA2PMAPixelNoCheck(srcColor);
       
   270 		const TUint32 noAlphaSrcColor=srcColor&0xFFFFFF;
       
   271 		while (aMaskBuffer < maskBufferPtrLimit)
       
   272 			{
       
   273 			const TUint maskAlpha=*aMaskBuffer;
       
   274 			if (maskAlpha)
       
   275 				{
       
   276 				if (maskAlpha==0xFF)
       
   277 					PMABlend_noChecksInplace(*pixelPtr, ffMaskColor, srcAlpha);
       
   278 				else
       
   279 					{
       
   280 					TUint32 mixedAlpha = ((maskAlpha+1) * srcAlpha)>>8;
       
   281 					PMABlend_FromNonPmAndAlpha(*pixelPtr, noAlphaSrcColor, mixedAlpha);
       
   282 					}
       
   283 				}
       
   284 			pixelPtr += pixelPtrInc;
       
   285 			aMaskBuffer++;
       
   286 			}
       
   287 		}
       
   288 	}
       
   289 
       
   290 /**
       
   291 @see CFbsDrawDevice::WriteRgb
       
   292 */
       
   293 void CDrawThirtyTwoBppBitmapAlphaPM::WriteRgb(TInt aX,TInt aY,TRgb aColor)
       
   294 	{
       
   295 	TUint32 srcColor = NonPMA2PMAPixel(aColor.Internal());
       
   296 	TUint32* pixelPtr = PixelAddress(aX,aY);
       
   297 	PMAInplaceBlend(*pixelPtr, srcColor);
       
   298 	}
       
   299 
       
   300 /**
       
   301 @see CFbsDrawDevice::WriteBinary
       
   302 */
       
   303 void CDrawThirtyTwoBppBitmapAlphaPM::WriteBinary(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,TInt aHeight,TRgb aColor)
       
   304 	{
       
   305 	const TUint32 colorInternal=aColor.Internal();
       
   306 	const TUint8  srcAlpha = colorInternal >> 24;
       
   307 	if (srcAlpha==0)
       
   308 		return;
       
   309 	DeOrientate(aX,aY);
       
   310 
       
   311 	TInt pixelInc;
       
   312 	TInt rowInc;
       
   313 
       
   314 	switch(iOrientation)
       
   315 		{
       
   316 		case EOrientationNormal:
       
   317 			{
       
   318 			pixelInc = 1;
       
   319 			rowInc = iScanLineWords;
       
   320 			break;
       
   321 			}
       
   322 		case EOrientationRotated90:
       
   323 			{
       
   324 			pixelInc = iScanLineWords;
       
   325 			rowInc = -1;
       
   326 			break;
       
   327 			}
       
   328 		case EOrientationRotated180:
       
   329 			{
       
   330 			pixelInc = -1;
       
   331 			rowInc = -iScanLineWords;
       
   332 			break;
       
   333 			}
       
   334 		default: // EOrientationRotated270
       
   335 			{
       
   336 			pixelInc = -iScanLineWords;
       
   337 			rowInc = 1;
       
   338 			}
       
   339 		}
       
   340 
       
   341 	const TUint32* dataLimit = aBuffer + aHeight;
       
   342 	const TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
       
   343 
       
   344 	TUint32* pixelPtr = PixelAddress(aX,aY);
       
   345 	if (srcAlpha==0xFF)
       
   346 		{
       
   347 		while (aBuffer < dataLimit)
       
   348 			{
       
   349 			TUint32 dataWord = *aBuffer++;
       
   350 			TUint32 dataMask = 1;
       
   351 			TUint32* tempPixelPtr = pixelPtr;
       
   352 			while (dataMask != dataMaskLimit)
       
   353 				{
       
   354 				if(dataWord & dataMask)
       
   355 					{
       
   356 					*tempPixelPtr=colorInternal;
       
   357 					}
       
   358 
       
   359 				tempPixelPtr += pixelInc;
       
   360 				dataMask <<= 1;
       
   361 				}
       
   362 
       
   363 			pixelPtr += rowInc;
       
   364 			}
       
   365 		}
       
   366 	else
       
   367 		{
       
   368 		TUint32 src_rb;
       
   369 		TUint32 src_g;
       
   370 		TUint32 mask;
       
   371 	//pre-multiply the src color, before blending.
       
   372 		NonPMA2PMAPixelRBG(colorInternal,src_rb,src_g,mask);
       
   373 		while (aBuffer < dataLimit)
       
   374 			{
       
   375 			TUint32 dataWord = *aBuffer++;
       
   376 			TUint32 dataMask = 1;
       
   377 			TUint32* tempPixelPtr = pixelPtr;
       
   378 			while (dataMask != dataMaskLimit)
       
   379 				{
       
   380 				if(dataWord & dataMask)
       
   381 					{
       
   382 					PMABlend_fromRBandG(*tempPixelPtr, src_rb, src_g, mask);
       
   383 					}
       
   384 
       
   385 				tempPixelPtr += pixelInc;
       
   386 				dataMask <<= 1;
       
   387 				}
       
   388 
       
   389 			pixelPtr += rowInc;
       
   390 			}
       
   391 		}
       
   392 	}
       
   393 
       
   394 /**
       
   395 @see CFbsDrawDevice::WriteBinaryLineVertical
       
   396 */
       
   397 void CDrawThirtyTwoBppBitmapAlphaPM::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aBuffer,TInt aHeight,TRgb aColor,TBool aUp)
       
   398 	{
       
   399 	const TUint32 colorInternal=aColor.Internal();
       
   400 	const TInt sourceAlpha = colorInternal>>24;
       
   401 	if (sourceAlpha==0)
       
   402 		return;
       
   403 
       
   404 	DeOrientate(aX,aY);
       
   405 
       
   406 	TInt scanlineWordLength;
       
   407 
       
   408 	switch(iOrientation)
       
   409 		{
       
   410 		case EOrientationNormal:
       
   411 			scanlineWordLength = iScanLineWords;
       
   412 			break;
       
   413 		case EOrientationRotated90:
       
   414 			scanlineWordLength = -1;
       
   415 			break;
       
   416 		case EOrientationRotated180:
       
   417 			scanlineWordLength = -iScanLineWords;
       
   418 			break;
       
   419 		default: // EOrientationRotated270
       
   420 			scanlineWordLength = 1;
       
   421 		}
       
   422 
       
   423 	if (aUp)
       
   424 		scanlineWordLength = -scanlineWordLength;
       
   425 
       
   426 	TUint32* pixelPtr = PixelAddress(aX,aY);
       
   427 	const TUint32* pixelPtrLimit = pixelPtr + (aHeight * scanlineWordLength);
       
   428 	TUint32 dataWord = *aBuffer;
       
   429 	TUint32 dataMask = 1;
       
   430 
       
   431 	if (sourceAlpha==0xFF)
       
   432 		{
       
   433 		while(pixelPtr != pixelPtrLimit)
       
   434 			{
       
   435 			if(!dataMask)
       
   436 				{
       
   437 				dataMask = 1;
       
   438 				aBuffer++;
       
   439 				dataWord = *aBuffer;
       
   440 				}
       
   441 
       
   442 			if(dataWord & dataMask)
       
   443 				{
       
   444 				*pixelPtr = colorInternal;
       
   445 				}
       
   446 			dataMask <<= 1;
       
   447 			pixelPtr += scanlineWordLength;
       
   448 			}
       
   449 		}
       
   450 	else
       
   451 		{
       
   452 		TUint32 src_rb;
       
   453 		TUint32 src_g;
       
   454 		TUint32 mask;
       
   455 	//pre-multiply the src color, before blending.
       
   456 		NonPMA2PMAPixelRBG(colorInternal,src_rb,src_g,mask);
       
   457 		while(pixelPtr != pixelPtrLimit)
       
   458 			{
       
   459 			if(!dataMask)
       
   460 				{
       
   461 				dataMask = 1;
       
   462 				aBuffer++;
       
   463 				dataWord = *aBuffer;
       
   464 				}
       
   465 
       
   466 			if(dataWord & dataMask)
       
   467 				{
       
   468 				PMABlend_fromRBandG(*pixelPtr, src_rb, src_g, mask);
       
   469 				}
       
   470 			dataMask <<= 1;
       
   471 			pixelPtr += scanlineWordLength;
       
   472 			}
       
   473 		}
       
   474 	}
       
   475 
       
   476 /**
       
   477 @see CFbsDrawDevice::BlendRgbMulti
       
   478 */
       
   479 void CDrawThirtyTwoBppBitmapAlphaPM::BlendRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
       
   480 	{
       
   481 	const TInt sourceAlpha = aColor.Alpha();
       
   482 	if (sourceAlpha==255)// opaque
       
   483 		{
       
   484 		WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
       
   485 		return;
       
   486 		}
       
   487 	if (sourceAlpha==0)// transparent
       
   488 		return;
       
   489 	TUint32* pixelPtr = PixelAddress(aX,aY);
       
   490 	TUint32* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineWords);
       
   491 	TUint32* pixelPtrLimit = pixelPtr + aLength;
       
   492 
       
   493 	TUint32 srcValue = NonPMA2PMAPixel(aColor.Internal());
       
   494 	TUint32 src_c = srcValue & KRBMask;
       
   495 	TUint32 src_g = (srcValue & KAGMask)>>8;
       
   496 	const TUint32 mask = 0x0100 - sourceAlpha;
       
   497 	while (pixelPtr < pixelRowPtrLimit)
       
   498 		{
       
   499 		for (TUint32* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr++)
       
   500 			{
       
   501 			const TUint32 dst = *tempPixelPtr;
       
   502 			TUint32 dst_c = dst  & KRBMask;
       
   503 			dst_c = (src_c +  ((mask * dst_c)>>8)) & KRBMask;
       
   504 			const TUint32 dst_ag = (dst & KAGMask)>>8;
       
   505 			dst_c |= ((src_g +  ((mask * dst_ag)>>8)) & KRBMask)<<8;
       
   506 			*tempPixelPtr=dst_c;
       
   507 			}
       
   508 		pixelPtr += iScanLineWords;
       
   509 		pixelPtrLimit += iScanLineWords;
       
   510 		}
       
   511 	}
       
   512 
       
   513 /**
       
   514 @see CFbsDrawDevice::BlendLine
       
   515 */
       
   516 void CDrawThirtyTwoBppBitmapAlphaPM::BlendLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
       
   517 	{
       
   518 	TUint32* pixelPtr = PixelAddress(aX,aY);
       
   519 
       
   520 	const TUint32* bufferPtrLimit = aBuffer + aLength;
       
   521 	const TInt pixelPtrInc = (iOrientation == EOrientationNormal) ? 1 : PixelAddressIncrement();
       
   522 
       
   523 	while (aBuffer < bufferPtrLimit)
       
   524 		{
       
   525 		PMAInplaceBlend(*pixelPtr,  *aBuffer);
       
   526 		aBuffer++;
       
   527 		pixelPtr += pixelPtrInc;
       
   528 		}
       
   529 	}
       
   530 /**
       
   531 @see CFbsDrawDevice::ShadowArea
       
   532 */
       
   533 void CDrawThirtyTwoBppBitmapAlphaPM::ShadowArea(const TRect& aRect)
       
   534 	{
       
   535 	const TRect rect(DeOrientate(aRect));
       
   536 	__ASSERT_DEBUG(rect.iTl.iX>=0 && rect.iBr.iX<=iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
       
   537 	__ASSERT_DEBUG(rect.iTl.iY>=0 && rect.iBr.iY<=iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
       
   538 
       
   539 	TUint32* pixelPtr = PixelAddress(rect.iTl.iX,rect.iTl.iY);
       
   540 	TUint32* pixelRowPtrLimit = pixelPtr + (rect.Height() * iScanLineWords);
       
   541 
       
   542 	TUint32* pixelRowPtr = pixelPtr;
       
   543 	TUint32* pixelPtrLimit = pixelPtr + rect.Width();
       
   544 
       
   545 	if (iShadowMode & EFade)
       
   546 		{
       
   547 		while (pixelRowPtr < pixelRowPtrLimit)
       
   548 			{
       
   549 			TUint32* tempPixelPtr = pixelRowPtr;
       
   550 
       
   551 			while (tempPixelPtr < pixelPtrLimit)
       
   552 				{
       
   553 				const TUint32 color = *tempPixelPtr;
       
   554 #if defined(SYMBIAN_USE_FAST_FADING)
       
   555 				const TUint32 fast_fade_offset = NonPMA2PMAPixel((color & 0xff000000) | SYMBIAN_USE_FAST_FADING) & 0x00ffffff;
       
   556 				*tempPixelPtr++ = (color & 0xff000000) | ((((color & 0x00ffffff) >> 1) & ~0x00808080) + fast_fade_offset);
       
   557 #else
       
   558 				const TInt alpha = (color >> 24) + 1;
       
   559 				const TUint32 fadeMapOffset = ((alpha * iFadeMapOffset) >> 8) & 0xff;
       
   560 				const TUint32 wordFadeMapOffset = ((fadeMapOffset) << 16) | (fadeMapOffset);
       
   561 				const TUint32 rb = ((((color & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
       
   562 		  		const TUint32 g = ((((color & 0x0000ff00) * iFadeMapFactor) >> 16) + fadeMapOffset) << 8;
       
   563 		  		*tempPixelPtr++ = (color & 0xff000000) | rb | g;
       
   564 #endif
       
   565 				}
       
   566 			pixelRowPtr += iScanLineWords;
       
   567 			pixelPtrLimit += iScanLineWords;
       
   568 			}
       
   569 		}
       
   570 
       
   571 	if (iShadowMode & EShadow)
       
   572 		{
       
   573 		pixelRowPtr = pixelPtr;
       
   574 		pixelPtrLimit = pixelPtr + rect.Width();
       
   575 
       
   576 		while (pixelRowPtr < pixelRowPtrLimit)
       
   577 			{
       
   578 			TUint32* tempPixelPtr = pixelRowPtr;
       
   579 
       
   580 			while (tempPixelPtr < pixelPtrLimit)
       
   581 				{
       
   582 				const TUint32 color = *tempPixelPtr;
       
   583 				const TInt alpha = (color >> 24) + 1;
       
   584 				const TInt uLimit = ((0x40) * alpha) >> 8;
       
   585 				TInt r = (color >> 16) & 0xff;
       
   586 				r = (r > uLimit) ? (r-uLimit) : 0;
       
   587 				TInt g = (color >> 8) & 0xff;
       
   588 				g = (g > uLimit) ? (g - uLimit) : 0;
       
   589 				TInt b = color & 0xff;
       
   590 				b = (b > uLimit) ? (b - uLimit) : 0;
       
   591 				*tempPixelPtr++	=  (color & 0xff000000) | (r << 16) | (g << 8) | b;
       
   592 				}
       
   593 			pixelRowPtr += iScanLineWords;
       
   594 			pixelPtrLimit += iScanLineWords;
       
   595 			}
       
   596 		}
       
   597 	}
       
   598 
       
   599 /**
       
   600 @see CFbsDrawDevice::WriteLine
       
   601 */
       
   602 void CDrawThirtyTwoBppBitmapAlphaPM::WriteLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer,
       
   603 		CGraphicsContext::TDrawMode aDrawMode)
       
   604 	{
       
   605 	const TPoint originalPoint(aX,aY);
       
   606 	DeOrientate(aX,aY);//aX and aY - physical coordinates
       
   607 
       
   608 	__ASSERT_DEBUG(aX >= 0,Panic(EScreenDriverPanicOutOfBounds));
       
   609 	__ASSERT_DEBUG(aY >= 0,Panic(EScreenDriverPanicOutOfBounds));
       
   610 #if defined(_DEBUG)
       
   611 	switch (iOrientation)
       
   612 		{
       
   613 	case EOrientationNormal:
       
   614 		__ASSERT_DEBUG(aX + aLength <= iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
       
   615 		break;
       
   616 	case EOrientationRotated90:
       
   617 		__ASSERT_DEBUG(aY + aLength <= iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
       
   618 		break;
       
   619 	case EOrientationRotated180:
       
   620 		__ASSERT_DEBUG(aX - aLength >= -1,Panic(EScreenDriverPanicOutOfBounds));
       
   621 		break;
       
   622 	default: // EOrientationRotated270
       
   623 		__ASSERT_DEBUG(aY - aLength >= -1,Panic(EScreenDriverPanicOutOfBounds));
       
   624 		break;
       
   625 		}
       
   626 #endif
       
   627 	__ASSERT_DEBUG(aLength > 0,Panic(EScreenDriverPanicZeroLength));
       
   628 	__ASSERT_DEBUG(aBuffer,Panic(EScreenDriverPanicNullPointer));
       
   629 
       
   630 	MapBufferToUserDisplayMode(aLength,aBuffer);
       
   631 	if(iShadowMode)
       
   632 		{
       
   633 		ShadowBuffer(aLength,aBuffer);
       
   634 		}
       
   635 	if(aDrawMode&CGraphicsContext::EInvertPen)
       
   636 		{
       
   637 #if defined(_DEBUG)
       
   638 		// code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
       
   639 //		RDebug::Printf("Premultiplied alpha mode invert pen behaviour not defined / implemented");
       
   640 #endif
       
   641 		// no-operation
       
   642 		}
       
   643 	if(aDrawMode&CGraphicsContext::EPenmode)
       
   644 		{
       
   645 		BlendLine(aX,aY,aLength,aBuffer);
       
   646 		return;
       
   647 		}
       
   648 	if(aDrawMode&CGraphicsContext::EWriteAlpha)
       
   649 		{
       
   650 		CDrawThirtyTwoBppBitmapCommon::WriteLine(aX,aY,aLength,aBuffer);
       
   651 		return;
       
   652 		}
       
   653 	if(aDrawMode&CGraphicsContext::EInvertScreen)
       
   654 		{
       
   655 #if defined(_DEBUG)
       
   656 //		RDebug::Printf("Premultiplied alpha mode invert screen behaviour not defined / implemented");
       
   657 #endif
       
   658 		return; //no-operation
       
   659 		}
       
   660 	if(aDrawMode&CGraphicsContext::EXor)
       
   661 		{
       
   662 #if defined(_DEBUG)
       
   663 		// code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
       
   664 //		RDebug::Printf("Premultiplied alpha mode XOR operation not defined / implemented");
       
   665 #endif
       
   666 		return; //no-operation
       
   667 		}
       
   668 else if(aDrawMode&CGraphicsContext::EAnd)
       
   669 		{
       
   670 #if defined(_DEBUG)
       
   671 		// code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
       
   672 //		RDebug::Printf("Premultiplied alpha mode AND operation not defined / implemented");
       
   673 #endif
       
   674 		return; //no-operation
       
   675 		}
       
   676 	else if(aDrawMode&CGraphicsContext::EOr)
       
   677 		{
       
   678 #if defined(_DEBUG)
       
   679 //		RDebug::Printf("Premultiplied alpha mode OR operation not defined / implemented");
       
   680 #endif
       
   681 		return; //no-operation
       
   682 		}
       
   683 	}
       
   684 
       
   685 TRgb CDrawThirtyTwoBppBitmapAlphaPM::RgbColor(TUint32 aColor) const
       
   686 	{
       
   687 	return TRgb::_Color16MAP(aColor);
       
   688 	}
       
   689 
       
   690 TUint32 CDrawThirtyTwoBppBitmapAlphaPM::Color(const TRgb& aColor)
       
   691 	{
       
   692 	return aColor._Color16MAP();
       
   693 	}
       
   694 	
       
   695 TInt CDrawThirtyTwoBppBitmapAlphaPM::WriteRgbOutlineAndShadow(TInt aX, TInt aY, const TInt aLength,
       
   696 															TUint32 aOutlinePenColor, TUint32 aShadowColor,
       
   697 															TUint32 aFillColor, const TUint8* aDataBuffer)
       
   698 	{
       
   699 	const TUint alphaShifted = aOutlinePenColor & 0xff000000;
       
   700 	const TUint alpha = alphaShifted>>24;
       
   701 	if (alpha==0 || aLength<=0)
       
   702 		return KErrNone;
       
   703 	DeOrientate(aX,aY);
       
   704 	TUint32* pixelPtr = PixelAddress(aX,aY);
       
   705 	const TInt pixelPtrInc = PixelAddressIncrement();
       
   706 	const TUint8* dataBufferPtrLimit = aDataBuffer + aLength;
       
   707 	TInt blendedRedColor;
       
   708 	TInt blendedGreenColor;
       
   709 	TInt blendedBlueColor;
       
   710 	TUint8 index = 0;
       
   711 	TUint32 finalColor;
       
   712 
       
   713 	//Get red color. Equivalent to TRgb::Red()
       
   714 	const TInt redOutlinePenColor = (aOutlinePenColor & 0xff0000) >> 16;
       
   715 	const TInt redShadowColor = (aShadowColor & 0xff0000) >> 16;
       
   716 	const TInt redFillColor = (aFillColor & 0xff0000) >> 16;
       
   717 
       
   718 	//Get green color. Equivalent to TRgb::Green()
       
   719 	const TInt greenOutlinePenColor = (aOutlinePenColor & 0xff00) >> 8;
       
   720 	const TInt greenShadowColor = (aShadowColor & 0xff00) >> 8;
       
   721 	const TInt greenFillColor = (aFillColor & 0xff00) >> 8;
       
   722 
       
   723 	//Get blue color. Equivalent to TRgb::Blue()
       
   724 	const TInt blueOutlinePenColor = aOutlinePenColor & 0xff;
       
   725 	const TInt blueShadowColor = aShadowColor & 0xff;
       
   726 	const TInt blueFillColor = aFillColor & 0xff;
       
   727 	const TUint16* normTable = PtrTo16BitNormalisationTable();
       
   728 
       
   729 	// Calculate PMA values for aFillColor & aOutlinePenColor that we can use for fast blending in the simple cases
       
   730 	// Don't pre calculate PMA version of aShadowColor as it is presumed not to be used enough to make this worthwhile
       
   731 	const TUint32 pmaFillColor = NonPMA2PMAPixel((aFillColor&0x00FFFFFF)|alphaShifted);
       
   732 	const TUint32 pmaOutlineColor = NonPMA2PMAPixel(aOutlinePenColor);
       
   733 	while (aDataBuffer < dataBufferPtrLimit)
       
   734 		{
       
   735 		TUint backgroundAlpha;
       
   736 		TUint outlineAlpha;
       
   737 		TUint shadowAlpha;
       
   738 		TUint fillAlpha;
       
   739 		index = *aDataBuffer++;
       
   740 		backgroundAlpha = FourColorBlendLookup[index][KBackgroundColorIndex];
       
   741 		if (backgroundAlpha == 255)
       
   742 			{
       
   743 			//background colour
       
   744 			//No drawing required so move on to next pixel.
       
   745 			pixelPtr += pixelPtrInc;
       
   746 			continue;
       
   747 			}
       
   748 		fillAlpha=FourColorBlendLookup[index][KFillColorIndex];
       
   749 		if (fillAlpha == 255)
       
   750 			{
       
   751 			//Use fill colour to draw
       
   752 			finalColor = pmaFillColor;
       
   753 oneColorBlend:
       
   754 			if (alpha==0xFF)
       
   755 				*pixelPtr=finalColor;
       
   756 			else
       
   757 				PMABlend_noChecksInplace(*pixelPtr, finalColor, alpha);
       
   758 			pixelPtr += pixelPtrInc;
       
   759 			continue;
       
   760 			}
       
   761 		outlineAlpha = FourColorBlendLookup[index][KOutlineColorIndex];
       
   762 		if (outlineAlpha == 255)
       
   763 			{
       
   764 			//Use outline colour to draw
       
   765 			finalColor = pmaOutlineColor;
       
   766 			goto oneColorBlend;
       
   767 			}
       
   768 		shadowAlpha = FourColorBlendLookup[index][KShadowColorIndex];
       
   769 		if (shadowAlpha == 255)
       
   770 			{
       
   771 			//Use shadow colour to draw
       
   772 			finalColor = NonPMA2PMAPixel((aShadowColor&0x00FFFFFF)|alphaShifted);
       
   773 			goto oneColorBlend;
       
   774 			}
       
   775 		blendedRedColor = redOutlinePenColor * outlineAlpha + 
       
   776 					   		redShadowColor * shadowAlpha +
       
   777 					  		redFillColor * fillAlpha;
       
   778 
       
   779 		blendedGreenColor = greenOutlinePenColor * outlineAlpha + 
       
   780 							greenShadowColor * shadowAlpha +
       
   781 							greenFillColor * fillAlpha;
       
   782 
       
   783 		blendedBlueColor = blueOutlinePenColor * outlineAlpha + 
       
   784 							blueShadowColor * shadowAlpha +
       
   785 							blueFillColor * fillAlpha;
       
   786 		if (backgroundAlpha)
       
   787 			{
       
   788 			const TUint32 backgroundColor = PMA2NonPMAPixel(*pixelPtr, normTable);
       
   789 			blendedRedColor += ((backgroundColor & 0xff0000) >> 16) * backgroundAlpha;
       
   790 			blendedGreenColor += ((backgroundColor & 0xff00) >> 8) * backgroundAlpha;
       
   791 			blendedBlueColor += (backgroundColor & 0xff) * backgroundAlpha;
       
   792 			}
       
   793 		finalColor = ((blendedRedColor&0xFF00)<<8) | (blendedGreenColor&0xFF00) | (blendedBlueColor>>8);
       
   794 
       
   795 		if (alpha==0xFF)
       
   796 			*pixelPtr=finalColor|0xFF000000;
       
   797 		else
       
   798 			{
       
   799 			//pre-multiply, inplace.
       
   800 			finalColor = NonPMA2PMAPixel(finalColor|alphaShifted);
       
   801 			PMABlend_noChecksInplace(*pixelPtr, finalColor, alpha);
       
   802 			}
       
   803 		pixelPtr += pixelPtrInc;
       
   804 		}
       
   805 	return KErrNone;
       
   806 	}