os/graphics/graphicsdeviceinterface/screendriver/sbit/BMDRAW32A.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2004-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 Performs a blend based on the PD method, with 2* 16 bit in one 32 bit operation optimisation.
    22 Note that this method assumes both input s are NOT alpha pre multiplied, but the output IS pre multiplied.
    23 The mechanism of this method is non-standard and non-intuitive, and is being addressed in 9.3 
    24 by developing distinct classes for the premultiplied and nonmultiplied cases.
    25 The mechanism remains hybrid to maintain compatibility and colour channel overflows caused by rounding
    26 overflows have been addressed.
    27 PD is basically CDest=CSrc*MulSrc+CDest*MulDest
    28 //A second optimisation is that multiplier value must be scaled from 0..255 to 0.0..1.0, this is 1/255 = 0.00392156.
    29 A second optimisation is that multiplier value must be scaled from 257..65535 to 0.0..1.0, this is 1/65535 = 0.0000152590.
    30 This used to be done by simply adding 1, giving 1..256/256 
    31 but this allows overflows to occur when the fractional parts are added together. 
    32 We want to keep adding the fractional parts as that gives a better result.
    33 Instead I am now using an approximation of 0.00392151, based on 255*257/256.
    34 To describe it imagine a "decimal" colour mode, where the channels count from 0..9, and 10-based operations are "efficient".
    35 We need 9 to generate 1.0 or 10/10 meaning "all".
    36 If we add 1, then we get 1..10 ==> 0.1 .. 1.0
    37 If we multiply by 1.1 then we get 0.0 .. 9.9. 
    38 And finally add a 0.5 rounding to the result.
    39 I do this multiply after the CSrc*MulSrc, while I still have a 16bit intermediate result.
    40 It is possible to generate a faster, less accurate result by exhaustively finding
    41 the highest value that can be added instead of rb = rb+((rb>>8)&0x00ff00ff)+0x00800080; without causing an overflow.
    42 @param aBeneath non-premultiplied color with alpha of the destination 
    43 @param aSrcColor non-premultiplied color with alpha of the source
    44 @param aMaskBuffer mask
    45 @return pre multiplied color resulting from the blending operation
    46 */
    47 FORCEINLINE TUint32 OptimizedBlend32A(TUint32 aBeneath,TUint32 aSrcColor,TUint8 aMaskBuffer)
    48  	{
    49 	if(aMaskBuffer)
    50 		{
    51 		if(aMaskBuffer == 0xff) // opaque, so unchanged
    52 			{
    53 			//Still need to convert source to destination from non-multiplied to pre-multiplied
    54 			//But this code resolves to a copy. The ARM optimiser prefers shifts over big constants.
    55 			return (aSrcColor|(aMaskBuffer<<24));
    56 			}
    57 		else
    58 			{
    59 			//0, 1, 2, 3 
    60 			//b, g, r, alpha  
    61 
    62 			const TUint32 srcMult = aMaskBuffer;
    63 			TUint32 destMult = ((255 - aMaskBuffer) * ((aBeneath >> 24)));
    64 			//This gives a slightly more accurate result than ((aBeneath >> 24)+1)
    65 			destMult=destMult+(destMult>>8);	 
    66 			destMult+= 0x0080;	  
    67 			destMult >>= 8;
    68 
    69 			TUint32 rb =(((aSrcColor&0x00ff00ff)*srcMult)) + (((aBeneath&0x00ff00ff)*destMult));
    70 			rb = rb+((rb>>8)&0x00ff00ff);
    71 			rb+=0x00800080;
    72 			rb>>=8;
    73 			TUint32 ag = (((aSrcColor&0x0000ff00)*srcMult)) + (((aBeneath&0x0000ff00)*destMult));
    74 			ag>>=8;	 //Note that if alpha is processed here, this shift must be performed before the multiplies
    75 			ag = ag+((ag>>8)&0x00ff00ff);
    76 			ag+=0x00800080;
    77 			TUint32 aa = srcMult+destMult;
    78 			return (rb&0x00ff00ff) | (ag&0x0000ff00) | (aa << 24);
    79 			
    80 			}
    81 		}
    82  	else // completely transparent
    83 		{
    84 		return aBeneath;
    85  		}
    86 
    87  	}
    88 
    89 TInt CDrawThirtyTwoBppBitmapAlpha::Construct(TSize aSize)
    90 	{
    91 	return Construct(aSize, aSize.iWidth << 2);
    92 	}
    93 
    94 TInt CDrawThirtyTwoBppBitmapAlpha::Construct(TSize aSize, TInt aStride)
    95 	{
    96 	iDispMode = EColor16MA;
    97 	return CDrawThirtyTwoBppBitmapCommon::Construct(aSize, aStride);
    98 	}
    99 
   100 void CDrawThirtyTwoBppBitmapAlpha::Shadow(TUint32& aColor)
   101 	{
   102 	TUint32 value = aColor & 0x00ffffff;
   103 	if (iShadowMode & EFade)
   104 		{
   105 #if defined(SYMBIAN_USE_FAST_FADING)
   106 		value = ((value >> 1) & ~0x00808080) + (SYMBIAN_USE_FAST_FADING);
   107 #else		
   108 		const TInt wordFadeMapOffset = ((iFadeMapOffset & 0xff) << 16) | (iFadeMapOffset & 0xff);
   109 		const TInt rb = ((((value & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
   110 	  	const TInt g = ((((value & 0x0000ff00) * iFadeMapFactor) >> 16) + iFadeMapOffset) << 8;
   111 		value = rb | g;
   112 #endif		
   113 		}
   114 
   115 	if (iShadowMode & EShadow)
   116 		{
   117 		const TInt r = (value & 0x00c00000) ? ((value & 0x00ff0000)-0x00400000) : 0;
   118 		const TInt g = (value & 0x0000c000) ? ((value & 0x0000ff00)-0x00004000) : 0;
   119 		const TInt b = (value & 0x000000c0) ? ((value & 0x000000ff)-0x00000040) : 0;
   120 		value = r | g | b;
   121 		}
   122 	// alpha is unchanged.
   123 	aColor = (aColor & 0xff000000) | value;
   124 	}
   125 
   126 /**
   127 MAlphaBlend::WriteRgbAlphaLine() implementation.
   128 @see MAlphaBlend::WriteRgbAlphaLine()
   129 */
   130 void CDrawThirtyTwoBppBitmapAlpha::WriteRgbAlphaLine(TInt aX, TInt aY, TInt aLength,
   131                                                   const TUint8* aRgbBuffer,
   132                                                   const TUint8* aMaskBuffer,
   133                                                   MAlphaBlend::TShadowing aShadowing,
   134                                                   CGraphicsContext::TDrawMode /*aDrawMode*/)
   135     {
   136     // precondition for this function is that the aRgbBuffer lies on a word boundary
   137     // Assert checks that the pointer is at a word boundary
   138     __ASSERT_DEBUG(!(((TUint)aRgbBuffer) & 0x3), Panic(EScreenDriverPanicInvalidPointer));
   139     
   140 	DeOrientate(aX,aY);
   141 	TUint32* pixelPtr = PixelAddress(aX,aY);
   142 	const TInt pixelPtrInc = PixelAddressIncrement();
   143 	const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
   144 	
   145 	// The purpose of this conditional is to remove if statements from within the loop 
   146 	// if shadow mode is not enabled and the UserDispMode is none or EColor16MA
   147 	if(!(iShadowMode & (EFade | EShadow)) && (iUserDispMode ==EColor16MA || iUserDispMode == ENone))
   148 		{
   149 		while (aMaskBuffer < maskBufferPtrLimit)
   150 			{
   151 			if(*aMaskBuffer)
   152 				{
   153 				*pixelPtr = OptimizedBlend32A(*pixelPtr, *((TUint32*)(aRgbBuffer)), *aMaskBuffer);
   154 				}
   155 			pixelPtr += pixelPtrInc;
   156 			aRgbBuffer += 4;
   157 			aMaskBuffer++;
   158 			}
   159 		}
   160 	else
   161 		{
   162 		while (aMaskBuffer < maskBufferPtrLimit)
   163 			{
   164 			if(*aMaskBuffer)
   165 				{
   166 				TUint32 srcColor = *((TUint32*)(aRgbBuffer));
   167 				if(aShadowing == MAlphaBlend::EShdwBefore)
   168 					{
   169 					Shadow(srcColor);
   170 					}
   171 				
   172 				TUint32 pixelClr = 0x0;
   173 				
   174 				pixelClr = OptimizedBlend32A(*pixelPtr, srcColor, *aMaskBuffer);
   175 
   176 				if(aShadowing == MAlphaBlend::EShdwAfter)
   177 					{
   178 					Shadow(pixelClr);
   179 					}
   180 					
   181 				if(iUserDispMode !=EColor16MA && iUserDispMode != ENone)
   182 					{
   183 					TInt red = TUint8(pixelClr >> 16);
   184 					TInt green = TUint8(pixelClr >> 8);
   185 					TInt blue = TUint8(pixelClr);
   186 					CDrawBitmap::MapColorToUserDisplayMode(red,green,blue);
   187 					pixelClr = (pixelClr&0xff000000) | (red << 16) | (green << 8) | blue;
   188 					}
   189 				*pixelPtr = pixelClr;
   190 				}
   191 			pixelPtr += pixelPtrInc;
   192 			aRgbBuffer += 4;
   193 			aMaskBuffer++;
   194 			}
   195 		}
   196 	}
   197 
   198 void CDrawThirtyTwoBppBitmapAlpha::WriteRgbAlphaMulti(TInt aX,TInt aY,TInt aLength,TRgb aColor,const TUint8* aMaskBuffer)
   199 	{
   200 	DeOrientate(aX,aY);
   201 	TUint32* pixelPtr = PixelAddress(aX,aY);
   202 	const TInt pixelPtrInc = PixelAddressIncrement();
   203 	const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
   204 
   205 	TUint32 srcColor = aColor.Internal();
   206 	if (iShadowMode)
   207 		Shadow(srcColor);
   208 
   209 	const TInt red   = (srcColor & 0x00ff0000) >> 16;
   210 	const TInt green = (srcColor & 0x0000ff00) >> 8;
   211 	const TInt blue  = srcColor & 0x000000ff;
   212 	const TInt alpha = srcColor >> 24;
   213 
   214 	if (alpha == 255)
   215 		{
   216 		// the most common case
   217 		// source is opaque, so we simply blend it using the mask
   218 		while (aMaskBuffer < maskBufferPtrLimit)
   219 			{
   220 
   221 			*pixelPtr = OptimizedBlend32A(*pixelPtr, srcColor, *aMaskBuffer);
   222 
   223 			pixelPtr += pixelPtrInc;
   224 			aMaskBuffer++;
   225 			}
   226 		}
   227 	else
   228 		{
   229 		// pen is semi-transparent, so we must blend using both the mask and pen alpha
   230 		while (aMaskBuffer < maskBufferPtrLimit)
   231 			{
   232 			TUint8* componentPtr = reinterpret_cast <TUint8*> (pixelPtr);
   233 			const TUint32 srcAlpha = alpha * aMaskBuffer[0];
   234 			const TUint32 srcMult = srcAlpha * 255;
   235 			const TUint32 destMult = (255*255 - srcAlpha) * componentPtr[3];
   236 			componentPtr[0] = TUint8(((blue * srcMult) + (componentPtr[0] * destMult)) / (255*255*255));
   237 			componentPtr[1] = TUint8(((green * srcMult) + (componentPtr[1] * destMult)) / (255*255*255));
   238 			componentPtr[2] = TUint8(((red * srcMult) + (componentPtr[2] * destMult)) / (255*255*255));
   239 			componentPtr[3] = TUint8((srcMult + destMult) / (255*255));
   240 			// ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha 
   241 
   242 			pixelPtr += pixelPtrInc;
   243 			aMaskBuffer++;
   244 			}
   245 		}
   246 	}
   247 
   248 void CDrawThirtyTwoBppBitmapAlpha::WriteRgb(TInt aX,TInt aY,TRgb aColor)
   249 	{
   250 	const TInt sourceAlpha = aColor.Alpha();
   251 
   252 	if(sourceAlpha==255)
   253 		{
   254 		TUint32* componentPtr = PixelAddress(aX,aY);
   255 		*componentPtr=aColor.Internal();
   256 		}
   257 	else if (sourceAlpha==0)
   258 		{
   259 		return;
   260 		}
   261 	else
   262 		{
   263 		TUint8* componentPtr = reinterpret_cast <TUint8*> (PixelAddress(aX,aY));
   264 		const TUint32 srcMult = sourceAlpha * 255;
   265 		const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
   266 		componentPtr[0] = TUint8(((aColor.Blue() * srcMult) + (componentPtr[0] * destMult)) / (255*255));
   267 		componentPtr[1] = TUint8(((aColor.Green() * srcMult) + (componentPtr[1] * destMult)) / (255*255));
   268 		componentPtr[2] = TUint8(((aColor.Red() * srcMult) + (componentPtr[2] * destMult)) / (255*255));
   269 		componentPtr[3] = TUint8((srcMult + destMult) / 255);
   270 		// ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha 
   271 		}
   272 	}
   273 
   274 void CDrawThirtyTwoBppBitmapAlpha::WriteBinary(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,TInt aHeight,TRgb aColor)
   275 	{
   276 	const TInt sourceAlpha = aColor.Alpha();
   277 	if (sourceAlpha==255)
   278 		{
   279 		CDrawThirtyTwoBppBitmapCommon::WriteBinary(aX,aY,aBuffer,aLength,aHeight,aColor);
   280 		return;
   281 		}
   282 	if (sourceAlpha==0)
   283 		return;
   284 
   285 	DeOrientate(aX,aY);
   286 
   287 	TInt pixelInc;
   288 	TInt rowInc;
   289 
   290 	switch(iOrientation)
   291 		{
   292 		case EOrientationNormal:
   293 			{
   294 			pixelInc = 1;
   295 			rowInc = iScanLineWords;
   296 			break;
   297 			}
   298 		case EOrientationRotated90:
   299 			{
   300 			pixelInc = iScanLineWords;
   301 			rowInc = -1;
   302 			break;
   303 			}
   304 		case EOrientationRotated180:
   305 			{
   306 			pixelInc = -1;
   307 			rowInc = -iScanLineWords;
   308 			break;
   309 			}
   310 		default: // EOrientationRotated270
   311 			{
   312 			pixelInc = -iScanLineWords;
   313 			rowInc = 1;
   314 			}	
   315 		}
   316 
   317 	const TUint32* dataLimit = aBuffer + aHeight;
   318 	const TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
   319 
   320 	TUint32* pixelPtr = PixelAddress(aX,aY);
   321 
   322 	const TInt sourceRed = aColor.Red();
   323 	const TInt sourceGreen = aColor.Green();
   324 	const TInt sourceBlue = aColor.Blue();
   325 
   326 	while (aBuffer < dataLimit)
   327 		{
   328 		TUint32 dataWord = *aBuffer++;
   329 		TUint32 dataMask = 1;
   330 		TUint32* tempPixelPtr = pixelPtr;
   331 
   332 		while (dataMask != dataMaskLimit)
   333 			{
   334 			if(dataWord & dataMask)
   335 				{
   336 				TUint8* componentPtr = reinterpret_cast <TUint8*> (tempPixelPtr);
   337 				const TUint32 srcMult = sourceAlpha * 255;
   338 				const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
   339 				componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
   340 				componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
   341 				componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
   342 				componentPtr[3] = TUint8((srcMult + destMult) / 255);
   343 				// ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha 
   344 				}
   345 
   346 			tempPixelPtr += pixelInc;
   347 			dataMask <<= 1;
   348 			}
   349 
   350 		pixelPtr += rowInc;
   351 		}
   352 	}
   353 
   354 void CDrawThirtyTwoBppBitmapAlpha::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aBuffer,TInt aHeight,TRgb aColor,TBool aUp)
   355 	{
   356 	const TInt sourceAlpha = aColor.Alpha();
   357 	if (sourceAlpha==255)
   358 		{
   359 		CDrawThirtyTwoBppBitmapCommon::WriteBinaryLineVertical(aX,aY,aBuffer,aHeight,aColor,aUp);
   360 		return;
   361 		}
   362 	if (sourceAlpha==0)
   363 		return;
   364 
   365 	DeOrientate(aX,aY);
   366 
   367 	TInt scanlineWordLength;
   368 
   369 	switch(iOrientation)
   370 		{
   371 		case EOrientationNormal:
   372 			scanlineWordLength = iScanLineWords;
   373 			break;
   374 		case EOrientationRotated90:
   375 			scanlineWordLength = -1;
   376 			break;
   377 		case EOrientationRotated180:
   378 			scanlineWordLength = -iScanLineWords;
   379 			break;
   380 		default: // EOrientationRotated270
   381 			scanlineWordLength = 1;	
   382 		}
   383 
   384 	if (aUp)
   385 		scanlineWordLength = -scanlineWordLength;
   386 
   387 	TUint32* pixelPtr = PixelAddress(aX,aY);
   388 	const TUint32* pixelPtrLimit = pixelPtr + (aHeight * scanlineWordLength);
   389 	TUint32 dataWord = *aBuffer;
   390 	TUint32 dataMask = 1;
   391 
   392 	const TInt sourceRed = aColor.Red();
   393 	const TInt sourceGreen = aColor.Green();
   394 	const TInt sourceBlue = aColor.Blue();
   395 
   396 	while(pixelPtr != pixelPtrLimit)
   397 		{
   398 		if(!dataMask)
   399 			{
   400 			dataMask = 1;
   401 			aBuffer++;
   402 			dataWord = *aBuffer;
   403 			}
   404 
   405 		if(dataWord & dataMask)
   406 			{
   407 			TUint8* componentPtr = reinterpret_cast <TUint8*> (pixelPtr);
   408 			const TUint32 srcMult = sourceAlpha * 255;
   409 			const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
   410 			componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
   411 			componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
   412 			componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
   413 			componentPtr[3] = TUint8((srcMult + destMult) / 255);
   414 			// ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha 
   415 			}
   416 
   417 		dataMask <<= 1;
   418 		pixelPtr += scanlineWordLength;
   419 		}
   420 	}
   421 
   422 void CDrawThirtyTwoBppBitmapAlpha::MapBufferToUserDisplayMode(TInt aLength,TUint32* aBuffer)
   423 	{
   424 	const TUint32* bufferLimit = aBuffer + aLength;
   425 	TRgb color;
   426 	
   427 	switch (iUserDispMode)
   428 		{
   429 	case EGray2:
   430 		while (aBuffer < bufferLimit)
   431 			{
   432 			color = TRgb::_Color16MA(*aBuffer);
   433 			color = TRgb::_Gray2(color._Gray2());
   434 			*aBuffer++ = color._Color16MA();
   435 			}
   436 		break;
   437 	case EGray4:
   438 		while (aBuffer < bufferLimit)
   439 			{
   440 			color = TRgb::_Color16MA(*aBuffer);
   441 			color = TRgb::_Gray4(color._Gray4());
   442 			*aBuffer++ = color._Color16MA();
   443 			}
   444 		break;
   445 	case EGray16:
   446 		while (aBuffer < bufferLimit)
   447 			{
   448 			color = TRgb::_Color16MA(*aBuffer);
   449 			color = TRgb::_Gray16(color._Gray16());
   450 			*aBuffer++ = color._Color16MA();
   451 			}
   452 		break;
   453 	case EGray256:
   454 		while (aBuffer < bufferLimit)
   455 			{
   456 			color = TRgb::_Color16MA(*aBuffer);
   457 			color = TRgb::_Gray256(color._Gray256());
   458 			*aBuffer++ = color._Color16MA();
   459 			}
   460 		break;
   461 	case EColor16:
   462 		while (aBuffer < bufferLimit)
   463 			{
   464 			color = TRgb::_Color16MA(*aBuffer);
   465 			color = TRgb::Color16(color.Color16());
   466 			*aBuffer++ = color._Color16MA();
   467 			}
   468 		break;
   469 	case EColor256:
   470 		while (aBuffer < bufferLimit)
   471 			{
   472 			color = TRgb::_Color16MA(*aBuffer);
   473 			color = TRgb::Color256(color.Color256());
   474 			*aBuffer++ = color._Color16MA();
   475 			}
   476 		break;
   477 	case EColor4K:
   478 		while (aBuffer < bufferLimit)
   479 			{
   480 			color = TRgb::_Color16MA(*aBuffer);
   481 			color = TRgb::_Color4K(color._Color4K());
   482 			*aBuffer++ = color._Color16MA();
   483 			}
   484 		break;
   485 	case EColor64K:
   486 		while (aBuffer < bufferLimit)
   487 			{
   488 			color = TRgb::_Color16MA(*aBuffer);
   489 			color = TRgb::_Color64K(color._Color64K());
   490 			*aBuffer++ = color._Color16MA();
   491 			}
   492 		break;
   493 	default:
   494 		break;
   495 		}
   496 	}
   497 
   498 void CDrawThirtyTwoBppBitmapAlpha::BlendRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
   499 	{
   500 	const TInt sourceAlpha = aColor.Alpha();
   501 	if (sourceAlpha==255)// opaque
   502 		{
   503 		WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
   504 		return;
   505 		}
   506 	if (sourceAlpha==0)// transparent
   507 		return;
   508 
   509 	TUint32* pixelPtr = PixelAddress(aX,aY);
   510 	TUint32* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineWords);
   511 	TUint32* pixelPtrLimit = pixelPtr + aLength;
   512 
   513 	const TInt sourceRed = aColor.Red();
   514 	const TInt sourceGreen = aColor.Green();
   515 	const TInt sourceBlue = aColor.Blue();
   516 	TUint srcValue = aColor._Color16MA();
   517 	while (pixelPtr < pixelRowPtrLimit)
   518 		{
   519 		for (TUint32* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr++)
   520 			{
   521 			// check that the alpha value is not 0xFF
   522 			if((*tempPixelPtr & 0xFF000000) ^ 0xFF000000)
   523 				{	
   524 				TUint8* componentPtr = reinterpret_cast <TUint8*> (tempPixelPtr);
   525 				const TUint32 srcMult = sourceAlpha * 255;
   526 				const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
   527 				componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
   528 				componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
   529 				componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
   530 				componentPtr[3] = TUint8((srcMult + destMult) / 255);
   531 				}
   532 			else
   533 				{	
   534 				AlphaBlendPixelToDest(srcValue, (TUint8)sourceAlpha, tempPixelPtr);
   535 				}
   536 
   537 			// ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha 
   538 			}
   539 
   540 		pixelPtr += iScanLineWords;
   541 		pixelPtrLimit += iScanLineWords;
   542 		}
   543 	}
   544 
   545 void CDrawThirtyTwoBppBitmapAlpha::BlendLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
   546 	{
   547 	TUint32* pixelPtr = PixelAddress(aX,aY);
   548 
   549 	const TUint32* bufferPtrLimit = aBuffer + aLength;
   550 	const TInt pixelPtrInc = (iOrientation == EOrientationNormal) ? 1 : PixelAddressIncrement();
   551 				
   552 	while (aBuffer < bufferPtrLimit)
   553 		{
   554 		*pixelPtr = OptimizedBlend32A(*pixelPtr,  *aBuffer, (*aBuffer)>>24);
   555 		
   556 		aBuffer++;
   557 		pixelPtr += pixelPtrInc;
   558 		}
   559 	}
   560 
   561 TRgb CDrawThirtyTwoBppBitmapAlpha::RgbColor(TUint32 aColor) const
   562 	{
   563 	return TRgb::_Color16MA(aColor);
   564 	}
   565 
   566 TUint32 CDrawThirtyTwoBppBitmapAlpha::Color(const TRgb& aColor)
   567 	{
   568 	return aColor._Color16MA();	
   569 	}
   570 
   571 void CDrawThirtyTwoBppBitmapAlpha::ShadowArea(const TRect& aRect)
   572 	{
   573 	const TRect rect(DeOrientate(aRect));
   574 
   575 	__ASSERT_DEBUG(rect.iTl.iX>=0 && rect.iBr.iX<=iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
   576 	__ASSERT_DEBUG(rect.iTl.iY>=0 && rect.iBr.iY<=iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
   577 
   578 	TUint32* pixelPtr = PixelAddress(rect.iTl.iX,rect.iTl.iY);
   579 	TUint32* pixelRowPtrLimit = pixelPtr + (rect.Height() * iScanLineWords);
   580 
   581 	TUint32* pixelRowPtr = pixelPtr;
   582 	TUint32* pixelPtrLimit = pixelPtr + rect.Width();
   583 
   584 	if (iShadowMode & EFade)
   585 		{
   586 #if !defined(SYMBIAN_USE_FAST_FADING)
   587 		const TInt wordFadeMapOffset = ((iFadeMapOffset & 0xff) << 16) | (iFadeMapOffset & 0xff);
   588 #endif
   589 		while (pixelRowPtr < pixelRowPtrLimit)
   590 			{
   591 			TUint32* tempPixelPtr = pixelRowPtr;
   592 
   593 			while (tempPixelPtr < pixelPtrLimit)
   594 				{
   595 				const TUint32 color = *tempPixelPtr;
   596 #if defined(SYMBIAN_USE_FAST_FADING)
   597 				*tempPixelPtr++ = (color & 0xff000000) | ((((color & 0x00ffffff) >> 1) & ~0x00808080) + (SYMBIAN_USE_FAST_FADING));
   598 #else
   599 				const TInt rb = ((((color & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
   600 			  	const TInt g = ((((color & 0x0000ff00) * iFadeMapFactor) >> 16) + iFadeMapOffset) << 8;
   601 				*tempPixelPtr++ = (color & 0xff000000) | rb | g;
   602 #endif				
   603 				}
   604 				
   605 			pixelRowPtr += iScanLineWords;
   606 			pixelPtrLimit += iScanLineWords;
   607 			}
   608 		}
   609 		
   610 	if (iShadowMode & EShadow)
   611 		{
   612 		pixelRowPtr = pixelPtr;
   613 		pixelPtrLimit = pixelPtr + rect.Width();
   614 		
   615 		while (pixelRowPtr < pixelRowPtrLimit)
   616 			{
   617 			TUint32* tempPixelPtr = pixelRowPtr;
   618 
   619 			while (tempPixelPtr < pixelPtrLimit)
   620 				{
   621 				const TUint32 color = *tempPixelPtr;
   622 				const TInt r = (color & 0x00c00000) ? ((color & 0x00ff0000)-0x00400000) : 0;
   623 				const TInt g = (color & 0x0000c000) ? ((color & 0x0000ff00)-0x00004000) : 0;
   624 				const TInt b = (color & 0x000000c0) ? ((color & 0x000000ff)-0x00000040) : 0;
   625 				*tempPixelPtr++	= (color & 0xff000000) | r | g | b;
   626 				}
   627 
   628 			pixelRowPtr += iScanLineWords;
   629 			pixelPtrLimit += iScanLineWords;
   630 			}
   631 		}
   632 	}
   633 
   634 TInt CDrawThirtyTwoBppBitmapAlpha::WriteRgbOutlineAndShadow(TInt aX, TInt aY, const TInt aLength,
   635 															TUint32 aOutlinePenColor, TUint32 aShadowColor,
   636 															TUint32 aFillColor, const TUint8* aDataBuffer)
   637 	{
   638 	DeOrientate(aX,aY);
   639 	TUint32* pixelPtr = PixelAddress(aX,aY);
   640 	const TInt pixelPtrInc = PixelAddressIncrement();
   641 	const TUint8* dataBufferPtrLimit = aDataBuffer + aLength;
   642 	TInt blendedRedColor;
   643 	TInt blendedGreenColor;
   644 	TInt blendedBlueColor;
   645 	TInt blendedAlpha;
   646 	TUint8 index = 0;
   647 	TUint32 finalColor;
   648 	const TUint16* normTable = PtrTo16BitNormalisationTable();
   649 
   650 	//Get red color. Equivalent to TRgb::Red()
   651 	const TInt redOutlinePenColor = (aOutlinePenColor & 0xff0000) >> 16;
   652 	const TInt redShadowColor = (aShadowColor & 0xff0000) >> 16;
   653 	const TInt redFillColor = (aFillColor & 0xff0000) >> 16;
   654 
   655 	//Get green color. Equivalent to TRgb::Green()
   656 	const TInt greenOutlinePenColor = (aOutlinePenColor & 0xff00) >> 8;
   657 	const TInt greenShadowColor = (aShadowColor & 0xff00) >> 8;
   658 	const TInt greenFillColor = (aFillColor & 0xff00) >> 8;
   659 
   660 	//Get blue color. Equivalent to TRgb::Blue()
   661 	const TInt blueOutlinePenColor = aOutlinePenColor & 0xff;
   662 	const TInt blueShadowColor = aShadowColor & 0xff;
   663 	const TInt blueFillColor = aFillColor & 0xff;
   664 
   665 	//Get alpha color. Equivalent to TRgb::Alpha()
   666 	const TInt alphaOutlinePenColor = aOutlinePenColor >> 24;
   667 	const TInt alphaShadowColor = aShadowColor >> 24;
   668 	const TInt alphaFillColor = aFillColor >> 24;
   669 
   670 	while (aDataBuffer < dataBufferPtrLimit)
   671 		{
   672 		index = *aDataBuffer++;
   673 		if(255 == FourColorBlendLookup[index][KBackgroundColorIndex])
   674 			{
   675 			//background colour
   676 			//No drawing required
   677 			}
   678 		else if (255 == FourColorBlendLookup[index][KFillColorIndex])
   679 			{
   680 			//Use fill colour to draw
   681 			finalColor = OptimizedBlend32A(*pixelPtr, aFillColor, alphaFillColor);
   682 			*pixelPtr = PMA2NonPMAPixel(finalColor, normTable);
   683 			}
   684 		else if (255 == FourColorBlendLookup[index][KShadowColorIndex])
   685 			{
   686 			//Use shadow colour to draw
   687 			finalColor = OptimizedBlend32A(*pixelPtr, aShadowColor, alphaShadowColor);
   688 			*pixelPtr = PMA2NonPMAPixel(finalColor, normTable);
   689 			}
   690 		else if (255 == FourColorBlendLookup[index][KOutlineColorIndex])
   691 			{
   692 			//Use outline colour to draw
   693 			finalColor = OptimizedBlend32A(*pixelPtr, aOutlinePenColor, alphaOutlinePenColor);
   694 			*pixelPtr = PMA2NonPMAPixel(finalColor, normTable);
   695 			}
   696 		else
   697 			{
   698 			blendedRedColor = (redOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor + 
   699 								redShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
   700 								redFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
   701 	
   702 			blendedGreenColor = (greenOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor  + 
   703 								greenShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
   704 								greenFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
   705 	
   706 			blendedBlueColor = (blueOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor  + 
   707 								blueShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
   708 								blueFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
   709 	
   710 			blendedAlpha = (alphaOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] + 
   711 							alphaShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
   712 							alphaFillColor * FourColorBlendLookup[index][KFillColorIndex]) >> 8;
   713 
   714 			// The blended colours have been alpha multiplied, hence the resulting colour is 16MAP
   715 			// Before doing the OptimizedBlend with the destination, note the following
   716 			//	- The source alpha is set as fully opaque so that the blend is just with the mask
   717 			//	- Input parameters for OptimizedBlend are NON-PRE, hence conversion from PRE to NON-PRE beforehand
   718 			//	- output parameter for OptimizedBlend is PRE, hence conversion from PRE to NON-PRE afterwards
   719 			finalColor = PMA2NonPMAPixel((blendedAlpha << 24) | (blendedRedColor << 16) | (blendedGreenColor << 8) | blendedBlueColor, normTable);
   720 			finalColor = OptimizedBlend32A(*pixelPtr, finalColor | 0xff000000, blendedAlpha);
   721 			*pixelPtr = PMA2NonPMAPixel(finalColor, normTable);
   722 			}
   723 		pixelPtr += pixelPtrInc;
   724 		}
   725 	return KErrNone;
   726 	}