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