os/graphics/graphicsdeviceinterface/screendriver/sbit/BMDRAW32PMA.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-2010 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 	DeOrientate(aX,aY);
   700 	TUint32* pixelPtr = PixelAddress(aX,aY);
   701 	const TInt pixelPtrInc = PixelAddressIncrement();
   702 	const TUint8* dataBufferPtrLimit = aDataBuffer + aLength;
   703 	TInt blendedRedColor;
   704 	TInt blendedGreenColor;
   705 	TInt blendedBlueColor;
   706 	TInt blendedAlpha;
   707 	TUint8 index = 0;
   708 	TUint32 finalColor;
   709 
   710 	//Get red color. Equivalent to TRgb::Red()
   711 	const TInt redOutlinePenColor = (aOutlinePenColor & 0xff0000) >> 16;
   712 	const TInt redShadowColor = (aShadowColor & 0xff0000) >> 16;
   713 	const TInt redFillColor = (aFillColor & 0xff0000) >> 16;
   714 
   715 	//Get green color. Equivalent to TRgb::Green()
   716 	const TInt greenOutlinePenColor = (aOutlinePenColor & 0xff00) >> 8;
   717 	const TInt greenShadowColor = (aShadowColor & 0xff00) >> 8;
   718 	const TInt greenFillColor = (aFillColor & 0xff00) >> 8;
   719 
   720 	//Get blue color. Equivalent to TRgb::Blue()
   721 	const TInt blueOutlinePenColor = aOutlinePenColor & 0xff;
   722 	const TInt blueShadowColor = aShadowColor & 0xff;
   723 	const TInt blueFillColor = aFillColor & 0xff;
   724 
   725 	//Get alpha color. Equivalent to TRgb::Alpha()
   726 	const TInt alphaOutlinePenColor = aOutlinePenColor >> 24;
   727 	const TInt alphaShadowColor = aShadowColor >> 24;
   728 	const TInt alphaFillColor = aFillColor >> 24;
   729 
   730 	// Calculate PMA values for aFillColor & aOutlinePenColor that we can use for fast blending in the simple cases
   731 	// Don't pre calculate PMA version of aShadowColor as it is presumed not to be used enough to make this worthwhile
   732 	const TUint32 pmaFillColor = NonPMA2PMAPixel(aFillColor);
   733 	const TUint32 pmaOutlineColor = NonPMA2PMAPixel(aOutlinePenColor);
   734 
   735 	while (aDataBuffer < dataBufferPtrLimit)
   736 		{
   737 		index = *aDataBuffer++;
   738 		if (255 == FourColorBlendLookup[index][KBackgroundColorIndex])
   739 			{
   740 			//background colour
   741 			//No drawing required
   742 			}
   743 		else if (255 == FourColorBlendLookup[index][KFillColorIndex])
   744 			{
   745 			//Use fill colour to draw
   746 			finalColor = pmaFillColor;
   747 			PMAInplaceBlend(*pixelPtr, finalColor);
   748 			}
   749 		else if (255 == FourColorBlendLookup[index][KOutlineColorIndex])
   750 			{
   751 			//Use outline colour to draw
   752 			finalColor = pmaOutlineColor;
   753 			PMAInplaceBlend(*pixelPtr, finalColor);
   754 			}
   755 		else if (255 == FourColorBlendLookup[index][KShadowColorIndex])
   756 			{
   757 			//Use shadow colour to draw
   758 			finalColor = NonPMA2PMAPixel(aShadowColor);
   759 			PMAInplaceBlend(*pixelPtr, finalColor);
   760 			}
   761 		else
   762 			{
   763 			blendedRedColor = (redOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor + 
   764 								redShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
   765 								redFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
   766 	
   767 			blendedGreenColor = (greenOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor  + 
   768 								greenShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
   769 								greenFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
   770 	
   771 			blendedBlueColor = (blueOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor  + 
   772 								blueShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
   773 								blueFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
   774 	
   775 			blendedAlpha = (alphaOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] + 
   776 							alphaShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
   777 							alphaFillColor * FourColorBlendLookup[index][KFillColorIndex]) >> 8;
   778 
   779 			finalColor = (blendedAlpha << 24) | (blendedRedColor << 16) | (blendedGreenColor  << 8 )| (blendedBlueColor);
   780 			PMAInplaceBlend(*pixelPtr, finalColor);
   781 			}
   782 		pixelPtr += pixelPtrInc;
   783 		}
   784 	return KErrNone;
   785 	}