os/graphics/graphicsdeviceinterface/screendriver/sbit/BMDRAW24U.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2003-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 "BitDrawInterfaceId.h"
    18 #include <graphics/lookuptable.h>
    19 #include <graphics/blendingalgorithms.h>
    20 
    21 TInt CDrawUTwentyFourBppBitmap::Construct(TSize aSize)
    22 	{
    23 	return Construct(aSize, aSize.iWidth << 2);
    24 	}
    25 
    26 TInt CDrawUTwentyFourBppBitmap::Construct(TSize aSize, TInt aStride)
    27 	{
    28 	iDispMode = EColor16MU;
    29 	return CDrawThirtyTwoBppBitmapCommon::Construct(aSize, aStride);
    30 	}
    31 
    32 /**
    33 MAlphaBlend::WriteRgbAlphaLine() implementation.
    34 @see MAlphaBlend::WriteRgbAlphaLine()
    35 */
    36 void CDrawUTwentyFourBppBitmap::WriteRgbAlphaLine(TInt aX, TInt aY, TInt aLength,
    37 													const TUint8* aRgbBuffer,
    38 													const TUint8* aMaskBuffer,
    39 													MAlphaBlend::TShadowing aShadowing,
    40 													CGraphicsContext::TDrawMode /*aDrawMode*/)
    41 	{
    42 	// precondition for this function is that the aRgbBuffer lies on a word boundary
    43     // Assert checks that the pointer is at a word boundary
    44     __ASSERT_DEBUG(!(((TUint)aRgbBuffer) & 0x3), Panic(EScreenDriverPanicInvalidPointer));
    45     
    46 	DeOrientate(aX,aY);
    47 	TUint32* pixelPtr = PixelAddress(aX,aY);
    48 	TUint32* rgbBuffer = (TUint32*)aRgbBuffer;
    49 	const TInt pixelPtrInc = PixelAddressIncrement();
    50 	const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
    51 	
    52 	if (!(iShadowMode & (EFade | EShadow)) && (iUserDispMode == ENone))
    53 		{
    54 		while (aMaskBuffer < maskBufferPtrLimit)
    55 			{
    56 			*pixelPtr = CalcAlphaPixel(*rgbBuffer, *aMaskBuffer, *pixelPtr);
    57 			aMaskBuffer++;
    58 			pixelPtr += pixelPtrInc;
    59 			rgbBuffer++;
    60 			}
    61 		}
    62 	else
    63 		{
    64 		while (aMaskBuffer < maskBufferPtrLimit)
    65 			{
    66 			TInt mask = *aMaskBuffer++;
    67 			if (mask)
    68 				{     
    69 				TInt b = aRgbBuffer[0];
    70 				TInt g = aRgbBuffer[1];
    71 				TInt r = aRgbBuffer[2];
    72 				if(aShadowing == MAlphaBlend::EShdwBefore)
    73 					{
    74 					if (iShadowMode & EFade)
    75 						{
    76 						r = ((r * iFadeMapFactor) >> 8) + iFadeMapOffset;
    77 						g = ((g * iFadeMapFactor) >> 8) + iFadeMapOffset;
    78 						b = ((b * iFadeMapFactor) >> 8) + iFadeMapOffset;
    79 						}
    80 					if (iShadowMode & EShadow)
    81 						{
    82 						r = (Max(0,r-0x40));
    83 						g = (Max(0,g-0x40));
    84 						b = (Max(0,b-0x40));
    85 						}
    86 					}
    87 				if (mask != 0xff)
    88 					{
    89 					// (mask * r + (255 - mask) * value) / 255 =
    90 					// ((257 * mask * (r - value)) >> 16) + value
    91 					TInt value = *pixelPtr & 0xffffff;
    92 					mask = (mask << 8) + mask; // mask = mask * 257
    93 					TInt v = value >> 16;
    94 					r = ((mask * (r - v)) >> 16) + v;
    95 					v = (value >> 8) & 0xff;
    96 					g = ((mask * (g - v)) >> 16) + v;
    97 					v = value & 0xff;
    98 					b = ((mask * (b - v)) >> 16) + v;
    99 					}
   100 				if(aShadowing == MAlphaBlend::EShdwAfter)
   101 					{
   102 					if (iShadowMode & EFade)
   103 						{  
   104 						r = ((r * iFadeMapFactor) >> 8) + iFadeMapOffset;
   105 						g = ((g * iFadeMapFactor) >> 8) + iFadeMapOffset;
   106 						b = ((b * iFadeMapFactor) >> 8) + iFadeMapOffset;            
   107 						}
   108 					if (iShadowMode & EShadow)
   109 						{
   110 						r = (Max(0,r-0x40));
   111 						g = (Max(0,g-0x40));
   112 						b = (Max(0,b-0x40));                  
   113 						}
   114 					}
   115 				// Convert colour if an incompatible UserDisplayMode is being used
   116 				CDrawBitmap::MapColorToUserDisplayMode(r,g,b);
   117 				*pixelPtr = (r<<16) | (g<<8) | b | 0xff000000;
   118 				}
   119 			aRgbBuffer += 4;
   120 			pixelPtr += pixelPtrInc;
   121 			}
   122 		}
   123 	}
   124 
   125 void CDrawUTwentyFourBppBitmap::ReadLine(TInt aX, TInt aY, TInt aLength, TAny* aBuffer, TDisplayMode aDispMode) const
   126 	{
   127 	if (aDispMode == EColor16MAP)
   128 		{
   129 		DeOrientate(aX, aY);
   130 		CDrawThirtyTwoBppBitmapCommon::ReadLine(aX, aY, aLength, aBuffer);
   131 		
   132 		//Overwrite unused byte with 0xff to produce valid 16MAP data
   133 		TUint8* alphaptr = (TUint8*) aBuffer+3;
   134 		TUint8* bufEnd = (TUint8*) aBuffer + (aLength << 2);
   135 		while (alphaptr < bufEnd)
   136 			{
   137 			*alphaptr = 0xff;
   138 			alphaptr+=4;
   139 			}
   140 		
   141 		return;
   142 		}
   143 	CDrawBitmap::ReadLine(aX, aY, aLength, aBuffer, aDispMode);
   144 	}
   145 
   146 void CDrawUTwentyFourBppBitmap::BlendRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
   147 	{
   148 	const TInt sourceAlpha = aColor.Alpha();
   149 	if (sourceAlpha==255)// opaque
   150 		{
   151 		WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
   152 		return;
   153 		}
   154 	if (sourceAlpha==0)// transparent
   155 		return;
   156 
   157 	TUint32* pixelPtr = PixelAddress(aX,aY);
   158 	TUint32* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineWords);
   159 	TUint32* pixelPtrLimit = pixelPtr + aLength;
   160 
   161 	const TUint32 sourceInternal=aColor.Internal();
   162 	const TUint32 s_rb = sourceInternal & 0x00FF00FF;
   163 	const TUint32 s_g = (sourceInternal & 0xFF00) >> 8;
   164 	const TUint32 mask2 = sourceAlpha | (sourceAlpha << 16);
   165 	while (pixelPtr < pixelRowPtrLimit)
   166 		{
   167 		for (TUint32* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr++)
   168 			{
   169 			const TUint32 d = *tempPixelPtr;
   170 			const TUint32 d_rb = d & 0x00FF00FF;
   171 			const TUint32 rb = ((((sourceAlpha * ((0x01000100 + s_rb) - d_rb)) >> 8) + d_rb) - mask2) & 0x00FF00FF;
   172 
   173 			const TInt d_g = (d & 0xFF00) >> 8;
   174 			const TInt g = ((sourceAlpha * (s_g - d_g)) >> 8) + d_g;
   175 	
   176 			*tempPixelPtr = rb | (g<<8) | 0xff000000;
   177 			}
   178 
   179 		pixelPtr += iScanLineWords;
   180 		pixelPtrLimit += iScanLineWords;
   181 		}
   182 	}
   183 
   184 void CDrawUTwentyFourBppBitmap::BlendLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
   185 	{
   186 	TUint32* pixelPtr = PixelAddress(aX,aY);
   187 
   188 	const TUint32* bufferPtrLimit = aBuffer + aLength;
   189 	const TInt pixelPtrInc = (iOrientation == EOrientationNormal) ? 1 : PixelAddressIncrement();
   190 				
   191 	while (aBuffer < bufferPtrLimit)
   192 		{
   193 		if((*aBuffer &0xFF000000) == 0xFF000000)
   194 			{
   195 			*pixelPtr = *aBuffer;
   196 			}
   197 		else if((*aBuffer & 0xFF000000))
   198 			{	
   199 			// specialization of pre-multiplied blending when the destination alpha is always 255
   200 			const TUint32 src_rb = *aBuffer & 0x00FF00FF;
   201 			const TUint32 src_g = *aBuffer & 0x0000FF00;
   202 			const TUint32 mask = 0x100 - (*aBuffer >> 24);
   203 			TUint32 dst_rb = *pixelPtr & 0x00FF00FF;
   204 			TUint32 dst_g = *pixelPtr & 0x0000FF00;
   205 			dst_rb = (src_rb + ((mask * dst_rb) >> 8)) & 0x00FF00FF;
   206 			dst_g = (src_g + ((mask * dst_g) >> 8)) & 0x0000FF00;
   207 			*pixelPtr = 0xFF000000 | dst_rb | dst_g;
   208 			}
   209 			
   210 		aBuffer++;
   211 		pixelPtr += pixelPtrInc;
   212 		}
   213 	}
   214 
   215 TRgb CDrawUTwentyFourBppBitmap::RgbColor(TUint32 aColor) const
   216 	{
   217 	return TRgb::_Color16MU(aColor);
   218 	}
   219 
   220 TUint32 CDrawUTwentyFourBppBitmap::Color(const TRgb& aColor)
   221 	{
   222 	return aColor._Color16MA() | 0xff000000;	
   223 	}
   224 
   225 
   226 // Copies an EColor64K pixel to an EColor16MU screen
   227 FORCEINLINE static void CopyPixel(const TUint16*& aSrcPtr, TUint32*& aDestPtr, TInt aPixelPtrInc, const TUint32* aHighAdd, const TUint16* aLowAdd)
   228 	{
   229 	*aDestPtr = aHighAdd[(*aSrcPtr) >> 8] | aLowAdd[(*aSrcPtr) & 0xff];
   230 	aDestPtr += aPixelPtrInc;
   231 	aSrcPtr++;
   232 	}
   233 
   234 
   235 // Copies two EColor64K pixels to an EColor16MU screen
   236 FORCEINLINE static void CopyTwoPixels(const TUint32*& aSrcPtr, TUint32*& aDestPtr, TInt aPixelPtrInc, const TUint32* aHighAdd, const TUint16* aLowAdd)
   237 	{
   238 	const TUint16* scanPtr = reinterpret_cast<const TUint16*&>(aSrcPtr);
   239 	*aDestPtr = aHighAdd[(*scanPtr) >> 8] | aLowAdd[(*scanPtr) & 0xff];
   240  	aDestPtr += aPixelPtrInc;
   241 	scanPtr++;
   242 	*aDestPtr = aHighAdd[(*scanPtr) >> 8] | aLowAdd[(*scanPtr) & 0xff];
   243  	aDestPtr += aPixelPtrInc;
   244  	aSrcPtr++;
   245 	}
   246 
   247 
   248 // Copies an EColor16MU pixel to an EColor16MU screen if necessary.
   249 FORCEINLINE static void ProcessMaskPixel(const TUint32*& aSrcPtr, const TUint32 aMaskWord, TUint32& aSingleBitMask, TUint32*& aDestPtr, TInt aPixelPtrInc)
   250 	{
   251 	if (aMaskWord & aSingleBitMask)
   252 		{
   253 		*aDestPtr = *aSrcPtr;
   254 		}
   255 	aSrcPtr++;
   256 	aDestPtr += aPixelPtrInc;
   257 	aSingleBitMask <<= 1;
   258 	}
   259 
   260 
   261 // Copies an EColor64K pixel to an EColor16MU screen if necessary.	
   262 FORCEINLINE static void ProcessMaskPixel(const TUint16*& aSrcPtr, const TUint32 aMaskWord, TUint32& aSingleBitMask, TUint32*& aDestPtr, TInt aPixelPtrInc, const TUint32* aHighAdd, const TUint16* aLowAdd)
   263 	{	
   264 	if (aMaskWord & aSingleBitMask)
   265 		{
   266 		*aDestPtr = aHighAdd[(*aSrcPtr) >> 8] | aLowAdd[(*aSrcPtr) & 0xff];
   267 		}
   268 	aSrcPtr++;
   269 	aDestPtr += aPixelPtrInc;
   270 	aSingleBitMask <<= 1;
   271 	}
   272 
   273 
   274 // Alpha-blends an EColor16MU pixel to an EColor16MU screen using a fixed mask value.
   275 FORCEINLINE static void BlendAlphaPixel(const TUint32*& aSrcPtr, const TUint8 aMask, TUint32*& aDestPtr, TInt aPixelPtrInc)
   276 	{
   277 	const TUint32 s = *aSrcPtr++;
   278 	const TUint32 d = *aDestPtr;
   279 	
   280 	// (a)  (mask * src + (255 - mask) * dest) / 255           This ideal formula
   281 	// (b)  ((mask * (src - dest)) >> 8) + dest                A faster approximation to (a)
   282 	// (c)  ((mask * (256 + src - dest) >> 8) + dest - mask    Equivalent to (b) but can be used on multiple colors at a time
   283 
   284 	const TUint32 s_rb = s & 0x00FF00FF;
   285 	const TUint32 d_rb = d & 0x00FF00FF;
   286 	const TUint32 mask2 = aMask | (aMask << 16);
   287 	const TUint32 rb = ((((aMask * ((0x01000100 + s_rb) - d_rb)) >> 8) + d_rb) - mask2) & 0x00FF00FF;
   288 
   289 	const TInt s_g = (s & 0xFF00) >> 8;
   290 	const TInt d_g = (d & 0xFF00) >> 8;
   291 	const TInt g = ((aMask * (s_g - d_g)) >> 8) + d_g;
   292 	
   293 	*aDestPtr = rb | (g<<8) | 0xff000000;
   294 	aDestPtr += aPixelPtrInc;
   295 	}
   296 
   297 
   298 // Alpha-blends an EColor16MU pixel to an EColor16MU screen if necessary.	
   299 FORCEINLINE static void ProcessAlphaPixel(const TUint32*& aSrcPtr, const TUint8*& aMaskPtr, TUint32*& aDestPtr, TInt aPixelPtrInc)
   300 	{
   301 	const TInt mask = *aMaskPtr++;
   302 
   303 	if (!mask)
   304 		{
   305 		// pixel is masked
   306 		aSrcPtr++;
   307 		aDestPtr += aPixelPtrInc;
   308 		}
   309 	else if (mask == 0xFF)
   310 		{
   311 		// pixel is unmasked
   312 		*aDestPtr = *aSrcPtr++;
   313 		aDestPtr += aPixelPtrInc;
   314 		}
   315 	else
   316 		{
   317 		BlendAlphaPixel(aSrcPtr, mask, aDestPtr, aPixelPtrInc);
   318 		}
   319 	}
   320 	
   321 
   322 // Alpha-blends an EColor64K pixel to an EColor16MU screen using a fixed mask value.
   323 FORCEINLINE static void BlendAlphaPixel(const TUint16*& aSrcPtr, const TUint8 aMask, TUint32*& aDestPtr, TInt aPixelPtrInc)
   324 	{
   325 	const TUint32 s = *aSrcPtr++;
   326 	const TUint32 d = *aDestPtr;
   327 	
   328 	// convert the source EColor64K red / blue pixels to EColor16MU
   329 	// the top two bits in EColor64K are used to fill the bottom two bits in EColor16MU
   330 	
   331 	const TUint32 s_rb = ((s & 0xF800) << 8) | ((s & 0xE000) << 3) | ((s & 0x1F) << 3) | ((s & 0x1C) >>2);	
   332 	const TUint32 d_rb = d & 0x00FF00FF;
   333 	const TUint32 mask2 = aMask | (aMask << 16);
   334 	const TUint32 rb = ((((aMask * ((0x01000100 + s_rb) - d_rb)) >> 8) + d_rb) - mask2) & 0x00FF00FF;
   335 	
   336 	// convert the source EColor64K green pixel to EColor16MU
   337 	const TInt s_g = ((s & 0x07E0) >> 3) | ((s & 0x0600) >> 9);
   338 	const TInt d_g = (d & 0xFF00) >> 8;
   339 	const TInt g = ((aMask * (s_g - d_g)) >> 8) + d_g;
   340 	
   341 	*aDestPtr = rb | (g<<8) | 0xff000000;
   342 	aDestPtr += aPixelPtrInc;
   343 	}
   344 
   345 	
   346 // Alpha-blends an EColor64K pixel to an EColor16MU screen if necessary.	
   347 FORCEINLINE static void ProcessAlphaPixel(const TUint16*& aSrcPtr, const TUint8*& aMaskPtr, TUint32*& aDestPtr, TInt aPixelPtrInc, const TUint32* aHighAdd, const TUint16* aLowAdd)
   348 	{
   349 	const TInt mask = *aMaskPtr++;
   350 
   351 	if (!mask)
   352 		{
   353 		// pixel is masked
   354 		aSrcPtr++;
   355 		aDestPtr += aPixelPtrInc;
   356 		}
   357 	else if (mask == 0xFF) 
   358 		{
   359 		// pixel is unmasked
   360 		CopyPixel(aSrcPtr, aDestPtr, aPixelPtrInc, aHighAdd, aLowAdd);
   361 		}
   362 	else
   363 		{
   364 		BlendAlphaPixel(aSrcPtr, mask, aDestPtr, aPixelPtrInc);
   365 		}
   366 	}
   367 
   368 
   369 /**
   370 CDrawUTwentyFourBppBitmap::WriteAlphaLineEx() implementation.
   371 @internalTechnology
   372 @see MFastBlit::WriteAlphaLineEx()
   373 */
   374 void CDrawUTwentyFourBppBitmap::WriteAlphaLineEx(TInt aX, TInt aY, TInt aLength, TInt aSrcX,
   375 													const TUint32* aSrcPtr,  TDisplayMode aSrcFormat,
   376 													TInt aMaskX, const TUint32* aMaskPtr,
   377 													MAlphaBlend::TShadowing aShadowing)
   378 	{
   379 	// Only certain pixel formats are supported.  Caller should check this.
   380 	__ASSERT_DEBUG(aSrcFormat ==EColor16MU || aSrcFormat ==EColor64K, User::Invariant());
   381 	
   382 	DeOrientate(aX,aY);
   383 	TUint32* pixelPtr = PixelAddress(aX,aY);
   384 	const TInt pixelPtrInc = PixelAddressIncrement();
   385 	
   386 	if (aSrcFormat==EColor16MU)
   387 		{		
   388 		if (!(iShadowMode & EFade) && !(iShadowMode & EShadow) && ((iUserDispMode==ENone) || (iUserDispMode==EColor16MU)) )
   389 			{
   390 			aSrcPtr += aSrcX;
   391 			const TUint32* maskWordPtr = aMaskPtr + (aMaskX >> 2);
   392 			const TInt startBit = aMaskX & 0x3;
   393 			
   394 			if (startBit)
   395 				{
   396 				// Process initial incomplete mask word
   397 				const TUint32 maskWord = *maskWordPtr++;
   398 				TInt numPix = Min(aLength, 4 - startBit);  // number of pixels to process from the first word of the mask
   399 				aLength -= numPix;
   400 				
   401 				if (!maskWord)
   402 					{
   403 					// maskWord is fully masked - skip the pixels
   404 					aSrcPtr += numPix;
   405 					pixelPtr += pixelPtrInc * numPix;
   406 					}
   407 				else if (maskWord == 0xFFFFFFFF)
   408 					{
   409 					// maskWord is fully unmasked - copy the pixels
   410 					while (numPix--)
   411 						{
   412 						*pixelPtr = *aSrcPtr++;
   413 						pixelPtr += pixelPtrInc;
   414 						}
   415 					}
   416 				else
   417 					{
   418 					// At least one of the pixels needs to be blended
   419 					const TUint8* maskPtr8 = reinterpret_cast<const TUint8*>(&maskWord);
   420 					maskPtr8 += startBit;
   421 					while (numPix--)
   422 						{
   423 						ProcessAlphaPixel(aSrcPtr, maskPtr8, pixelPtr, pixelPtrInc);
   424 						}
   425 					}
   426 				}
   427 			
   428 			TInt numMaskWords = aLength >> 2;
   429 			aLength &= 0x3;
   430 			while (numMaskWords--)
   431 				{
   432 				// Process a complete mask word - 4 pixels
   433 				const TUint32 maskWord = *maskWordPtr++;
   434 				
   435 				if (!maskWord)
   436 					{
   437 					// maskWord is fully masked - skip 4 pixels
   438 					aSrcPtr += 4;
   439 					pixelPtr += pixelPtrInc << 2;
   440 					}
   441 				else if (maskWord == 0xFFFFFFFF)
   442 					{
   443 					// maskWord is fully unmasked - copy 4 pixels
   444 					*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   445 					*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   446 					*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   447 					*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   448 					}
   449 				else
   450 					{	
   451 					// At least one of the 4 pixels needs to be blended
   452 					const TUint8* maskPtr8 = reinterpret_cast<const TUint8*>(&maskWord);
   453 
   454 					if (maskPtr8[0] && (maskPtr8[0] != 0xFF) &&
   455 						maskPtr8[1] && (maskPtr8[1] != 0xFF) &&
   456 						maskPtr8[2] && (maskPtr8[2] != 0xFF) &&
   457 						maskPtr8[3] && (maskPtr8[3] != 0xFF))
   458 						{
   459 						// Blend all 4 pixels inline
   460 						BlendAlphaPixel(aSrcPtr, maskPtr8[0], pixelPtr, pixelPtrInc);
   461 						BlendAlphaPixel(aSrcPtr, maskPtr8[1], pixelPtr, pixelPtrInc);
   462 						BlendAlphaPixel(aSrcPtr, maskPtr8[2], pixelPtr, pixelPtrInc);
   463 						BlendAlphaPixel(aSrcPtr, maskPtr8[3], pixelPtr, pixelPtrInc);
   464 						}
   465 					else
   466 						{
   467 						ProcessAlphaPixel(aSrcPtr, maskPtr8, pixelPtr, pixelPtrInc);
   468 						ProcessAlphaPixel(aSrcPtr, maskPtr8, pixelPtr, pixelPtrInc);
   469 						ProcessAlphaPixel(aSrcPtr, maskPtr8, pixelPtr, pixelPtrInc);
   470 						ProcessAlphaPixel(aSrcPtr, maskPtr8, pixelPtr, pixelPtrInc);
   471 						}
   472 					}
   473 				}
   474 
   475 			if (aLength)
   476 				{
   477 				const TUint32 maskWord = *maskWordPtr;
   478 				if (!maskWord)
   479 					{
   480 					// maskWord is fully masked - skip the pixels
   481 					return;
   482 					}
   483 				if (maskWord == 0xFFFFFFFF)
   484 					{
   485 					// maskWord is fully unmasked - copy the pixels
   486 					while (aLength--)
   487 						{
   488 						*pixelPtr = *aSrcPtr++;
   489 						pixelPtr += pixelPtrInc;
   490 						}
   491 					}
   492 				else
   493 					{
   494 					// At least one of the pixels needs to be blended
   495 					const TUint8* maskPtr8 = reinterpret_cast<const TUint8*>(&maskWord);
   496 					while (aLength--)
   497 						{
   498 						ProcessAlphaPixel(aSrcPtr, maskPtr8, pixelPtr, pixelPtrInc);
   499 						}
   500 					}
   501 				}
   502 			}
   503 		else
   504 			{
   505 			// Non-optimised path including shadowing and UserDisplayMode conversion
   506 			const TUint8* srcPtr8  = reinterpret_cast<const TUint8*>(aSrcPtr + aSrcX);
   507 			const TUint8* maskPtr8 = reinterpret_cast<const TUint8*>(aMaskPtr) + aMaskX;
   508 			
   509 			while (aLength--)
   510 				{
   511 				TInt mask = *maskPtr8++;
   512 				if (mask)
   513 					{
   514 					TInt b = srcPtr8[0];
   515 					TInt g = srcPtr8[1];
   516 					TInt r = srcPtr8[2];
   517 					if(aShadowing == MAlphaBlend::EShdwBefore)
   518 						{
   519 						if (iShadowMode & EFade)
   520 							{
   521 							r = ((r * iFadeMapFactor) >> 8) + iFadeMapOffset;
   522 							g = ((g * iFadeMapFactor) >> 8) + iFadeMapOffset;
   523 							b = ((b * iFadeMapFactor) >> 8) + iFadeMapOffset;
   524 							}
   525 						if (iShadowMode & EShadow)
   526 							{
   527 							r = (Max(0,r-0x40));
   528 							g = (Max(0,g-0x40));
   529 							b = (Max(0,b-0x40));
   530 							}
   531 						}
   532 					if (mask != 0xff)
   533 						{
   534 						// (mask * r + (255 - mask) * value) / 255 =
   535 						// ((257 * mask * (r - value)) >> 16) + value
   536 						TInt value = *pixelPtr & 0xffffff;
   537 						mask = (mask << 8) + mask; // mask = mask * 257
   538 						TInt v = value >> 16;
   539 						r = ((mask * (r - v)) >> 16) + v;
   540 						v = (value >> 8) & 0xff;
   541 						g = ((mask * (g - v)) >> 16) + v;
   542 						v = value & 0xff;
   543 						b = ((mask * (b - v)) >> 16) + v;
   544 						}
   545 					if(aShadowing == MAlphaBlend::EShdwAfter)
   546 						{
   547 						if (iShadowMode & EFade)
   548 							{  
   549 							r = ((r * iFadeMapFactor) >> 8) + iFadeMapOffset;
   550 							g = ((g * iFadeMapFactor) >> 8) + iFadeMapOffset;
   551 							b = ((b * iFadeMapFactor) >> 8) + iFadeMapOffset;            
   552 							}
   553 						if (iShadowMode & EShadow)
   554 							{
   555 							r = (Max(0,r-0x40));
   556 							g = (Max(0,g-0x40));
   557 							b = (Max(0,b-0x40));
   558 							}
   559 						}
   560 					// Convert colour if an incompatible UserDisplayMode is being used
   561 					CDrawBitmap::MapColorToUserDisplayMode(r,g,b);
   562 					*pixelPtr = (r<<16) | (g<<8) | b | 0xff000000;
   563 					}
   564 				pixelPtr += pixelPtrInc;
   565 				srcPtr8 += 4;
   566 				}
   567 			}
   568 		return;
   569 		}
   570 	else   // (aSrcFormat==EColor64K)
   571 		{
   572 		const TUint16* srcPtr16 = reinterpret_cast<const TUint16*>(aSrcPtr) + aSrcX;
   573 		
   574 		if (!(iShadowMode & EFade) && !(iShadowMode & EShadow) && ((iUserDispMode==ENone) || (iUserDispMode==EColor16MU)))
   575 			{			
   576 			const TUint16* lowAdd = Convert16to32bppLow();
   577 			const TUint32* highAdd = Convert16to32bppHigh();
   578 			const TUint32* maskWordPtr = aMaskPtr + (aMaskX >> 2);
   579 			const TInt startBit = aMaskX & 0x3;
   580 			
   581 			if (startBit)
   582 				{
   583 				// Process initial incomplete mask word
   584 				const TUint32 maskWord = *maskWordPtr++;
   585 				TInt numPix = Min(aLength, 4 - startBit);  // number of pixels to process from the first word of the mask
   586 				aLength -= numPix;
   587 				
   588 				if (!maskWord)
   589 					{
   590 					// maskWord is fully masked
   591 					srcPtr16 += numPix;
   592 					pixelPtr += pixelPtrInc * numPix;
   593 					}
   594 				else if (maskWord == 0xFFFFFFFF)
   595 					{
   596 					// maskWord is fully unmasked
   597 					while (numPix--)
   598 						{
   599 						CopyPixel(srcPtr16, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   600 						}
   601 					}
   602 				else
   603 					{
   604 					// At least one of the pixels needs to be blended
   605 					const TUint8* maskPtr8 = reinterpret_cast<const TUint8*>(&maskWord);
   606 					maskPtr8 += startBit;
   607 					while (numPix--)
   608 						{
   609 						ProcessAlphaPixel(srcPtr16, maskPtr8, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   610 						}
   611 					}
   612 				}
   613 			
   614 			TInt numMaskWords = aLength >> 2;
   615 			aLength &= 0x3;
   616 			while (numMaskWords--)
   617 				{
   618 				// Process 4 mask pixels
   619 				const TUint32 maskWord = *maskWordPtr++;
   620 				
   621 				if (!maskWord)
   622 					{
   623 					// maskWord is fully masked - skip 4 pixels
   624 					srcPtr16 += 4;
   625 					pixelPtr += pixelPtrInc << 2;
   626 					}
   627 				else if (maskWord == 0xFFFFFFFF)
   628 					{
   629 					// maskWord is fully unmasked - copy and convert 4 pixels
   630 					const TUint32* srcPtr32 = (const TUint32*)srcPtr16;
   631 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   632 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   633 					srcPtr16 = (const TUint16*)srcPtr32;
   634 					}
   635 				else
   636 					{	
   637 					// At least one of the 4 pixels needs to be blended
   638 					const TUint8* maskPtr8 = reinterpret_cast<const TUint8*>(&maskWord);
   639 
   640 					if (maskPtr8[0] && (maskPtr8[0] != 0xFF) &&
   641 						maskPtr8[1] && (maskPtr8[1] != 0xFF) &&
   642 						maskPtr8[2] && (maskPtr8[2] != 0xFF) &&
   643 						maskPtr8[3] && (maskPtr8[3] != 0xFF))
   644 						{
   645 						// Blend all 4 pixels inline
   646 						BlendAlphaPixel(srcPtr16, maskPtr8[0], pixelPtr, pixelPtrInc);
   647 						BlendAlphaPixel(srcPtr16, maskPtr8[1], pixelPtr, pixelPtrInc);
   648 						BlendAlphaPixel(srcPtr16, maskPtr8[2], pixelPtr, pixelPtrInc);
   649 						BlendAlphaPixel(srcPtr16, maskPtr8[3], pixelPtr, pixelPtrInc);
   650 						}
   651 					else
   652 						{
   653 						ProcessAlphaPixel(srcPtr16, maskPtr8, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   654 						ProcessAlphaPixel(srcPtr16, maskPtr8, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   655 						ProcessAlphaPixel(srcPtr16, maskPtr8, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   656 						ProcessAlphaPixel(srcPtr16, maskPtr8, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   657 						}
   658 					}
   659 				}
   660 
   661 			if (aLength)
   662 				{
   663 				// Process final incomplete mask word
   664 				const TUint32 maskWord = *maskWordPtr;   // this will over-read
   665 				if (!maskWord)
   666 					{
   667 					// maskWord is fully masked	- skip the pixels
   668 					return;
   669 					}
   670 				if (maskWord == 0xFFFFFFFF)
   671 					{
   672 					// maskWord is fully unmasked - copy and convert the pixels
   673 					while (aLength--)
   674 						{
   675 						CopyPixel(srcPtr16, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   676 						}
   677 					}
   678 				else
   679 					{
   680 					// At least one of the pixels needs to be blended
   681 					const TUint8* maskPtr8 = reinterpret_cast<const TUint8*>(&maskWord);
   682 					while (aLength--)
   683 						{
   684 						ProcessAlphaPixel(srcPtr16, maskPtr8, pixelPtr, pixelPtrInc, highAdd, lowAdd);
   685 						}
   686 					}
   687 				}
   688 			}
   689 		else
   690 			{
   691 			// Non-optimised path including shadowing and UserDisplayMode conversion
   692 			const TUint8* maskPtr8  = reinterpret_cast<const TUint8*>(aMaskPtr) + aMaskX;
   693 			while (aLength--)
   694 				{
   695 				TInt mask = *maskPtr8++;
   696 				if (mask)
   697 					{
   698 					const TUint32 src = *srcPtr16;
   699 					TInt r  = (src & 0xF800) >> 8;
   700 					     r |= (src & 0xE000) >>13;
   701 					TInt g  = (src & 0x07E0) >> 3;
   702 					     g |= (src & 0x0600) >> 9;
   703 					TInt b  = (src & 0x001F) << 3;
   704 					     b |= (src & 0x001C) >> 2;
   705 
   706 					if(aShadowing == MAlphaBlend::EShdwBefore)
   707 						{
   708 						if (iShadowMode & EFade)
   709 							{
   710 							r = ((r * iFadeMapFactor) >> 8) + iFadeMapOffset;
   711 							g = ((g * iFadeMapFactor) >> 8) + iFadeMapOffset;
   712 							b = ((b * iFadeMapFactor) >> 8) + iFadeMapOffset;
   713 							}
   714 						if (iShadowMode & EShadow)
   715 							{
   716 							r = Max(0,r-0x40);
   717 							g = Max(0,g-0x40);
   718 							b = Max(0,b-0x40);
   719 							}
   720 						}
   721 					if (mask != 0xff)
   722 						{
   723 						// (mask * r + (255 - mask) * value) / 255 =
   724 						// ((257 * mask * (r - value)) >> 16) + value
   725 						const TInt value = *pixelPtr & 0xffffff;
   726 						mask = (mask << 8) + mask; // mask = mask * 257
   727 						TInt v = value >> 16;
   728 						r = ((mask * (r - v)) >> 16) + v;
   729 						v = (value >> 8) & 0xff;
   730 						g = ((mask * (g - v)) >> 16) + v;
   731 						v = value & 0xff;
   732 						b = ((mask * (b - v)) >> 16) + v;
   733 						}
   734 					if(aShadowing == MAlphaBlend::EShdwAfter)
   735 						{
   736 						if (iShadowMode & EFade)
   737 							{  
   738 							r = ((r * iFadeMapFactor) >> 8) + iFadeMapOffset;
   739 							g = ((g * iFadeMapFactor) >> 8) + iFadeMapOffset;
   740 							b = ((b * iFadeMapFactor) >> 8) + iFadeMapOffset;            
   741 							}
   742 						if (iShadowMode & EShadow)
   743 							{
   744 							r = Max(0,r-0x40);
   745 							g = Max(0,g-0x40);
   746 							b = Max(0,b-0x40);                  
   747 							}
   748 						}
   749 					// Convert colour if an incompatible UserDisplayMode is being used
   750 					CDrawBitmap::MapColorToUserDisplayMode(r,g,b);
   751 					*pixelPtr = (r<<16) | (g<<8) | b | 0xff000000;
   752 					}
   753 				srcPtr16++;
   754 				pixelPtr += pixelPtrInc;
   755 				}
   756 			}
   757 		return;
   758 		}	
   759 	}
   760 
   761 /**
   762 CDrawUTwentyFourBppBitmap::WriteMaskLineEx() implementation.
   763 @internalTechnology
   764 @see MFastBlit::WriteMaskLineEx()
   765 */
   766 void CDrawUTwentyFourBppBitmap::WriteMaskLineEx(TInt aX, TInt aY, TInt aLength, TInt aSrcX,
   767 													const TUint32* aSrcPtr,  TDisplayMode aSrcFormat,
   768 													TInt aMaskX, const TUint32* aMaskPtr, TBool aInvertMask)
   769 	{
   770 	// Only certain pixel formats are supported.  Caller should check this.
   771 	__ASSERT_DEBUG(aSrcFormat ==EColor16MU || aSrcFormat ==EColor64K, User::Invariant());
   772 
   773 	DeOrientate(aX,aY);
   774 	TUint32* pixelPtr = PixelAddress(aX,aY);
   775 	const TInt pixelPtrInc = PixelAddressIncrement();
   776 	const TUint32 invertWord = (aInvertMask ? 0xFFFFFFFF : 0);  // to be XORed with the mask
   777 
   778 	if (aSrcFormat==EColor16MU)
   779 		{
   780 		aSrcPtr += aSrcX;
   781 	
   782 		if ((iUserDispMode==ENone) || (iUserDispMode==EColor16MU))
   783 			{
   784 			const TUint32* maskWordPtr = aMaskPtr + (aMaskX >> 5);
   785 			const TInt startBit = aMaskX & 0x1F;
   786 
   787 			if (startBit)
   788 				{
   789 				// Process initial incomplete mask word
   790 				TUint32 maskWord = *maskWordPtr++;
   791 				maskWord ^= invertWord;
   792 				TInt numPix = Min(aLength, 32 - startBit);  // number of pixels to process from the first word of the mask
   793 				aLength -= numPix;
   794 
   795 				if (!maskWord)
   796 					{
   797 					// maskWord is fully masked - skip the pixels
   798 					aSrcPtr += numPix;
   799 					pixelPtr += pixelPtrInc * numPix;
   800 					}
   801 				else if (maskWord == 0xFFFFFFFF)
   802 					{
   803 					// maskWord is fully unmasked - copy the pixels
   804 					while (numPix--)
   805 						{
   806 						*pixelPtr = *aSrcPtr++;
   807 						pixelPtr += pixelPtrInc;
   808 						}
   809 					}
   810 				else
   811 					{
   812 					// maskWord is partially masked - process each pixel
   813 					TUint32 singleBitMask = 1 << startBit;
   814 					while (numPix--)
   815 						{
   816 						ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   817 						}
   818 					}
   819 				}
   820 			
   821 			TInt numMaskWords = aLength >> 5;
   822 			aLength &= 0x1F;
   823 			while (numMaskWords--)
   824 				{
   825 				// Process a complete mask word (32 pixels)
   826 				TUint32 maskWord = *maskWordPtr++;
   827 				maskWord ^= invertWord;
   828 				
   829 				if (!maskWord)
   830 					{
   831 					// maskWord is fully masked - skip 32 pixels
   832 					aSrcPtr += 32;
   833 					pixelPtr += pixelPtrInc << 5;
   834 					}
   835 				else if (maskWord == 0xFFFFFFFF)
   836 					{
   837 					// maskWord is fully unmasked - copy 32 pixels
   838 					if (pixelPtrInc==1)
   839 						{
   840 						pixelPtr=(TUint32*)Mem::Move(pixelPtr, aSrcPtr, 128);
   841 						aSrcPtr+= 32;
   842 						}
   843 					else
   844 						{
   845 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   846 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   847 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   848 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   849 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   850 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   851 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   852 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   853 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   854 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   855 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   856 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   857 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   858 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   859 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   860 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   861 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   862 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   863 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   864 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   865 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   866 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   867 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   868 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   869 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   870 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   871 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   872 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   873 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   874 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   875 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   876 						*pixelPtr = *aSrcPtr++; pixelPtr += pixelPtrInc;
   877 						}
   878 					}
   879 				else
   880 					{	
   881 					// maskWord is partially masked - process each of the 32 pixels
   882 					TUint32 singleBitMask = 1;
   883 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   884 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   885 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   886 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   887 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   888 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   889 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   890 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   891 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   892 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   893 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   894 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   895 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   896 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   897 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   898 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   899 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   900 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   901 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   902 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   903 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   904 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   905 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   906 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   907 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   908 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   909 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   910 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   911 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   912 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   913 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   914 					ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   915 					}
   916 				}
   917 
   918 
   919 			if (aLength)
   920 				{
   921 				// Process final incomplete mask word
   922 				TUint32 maskWord = *maskWordPtr;
   923 				maskWord ^= invertWord;
   924 				
   925 				if (!maskWord)
   926 					{
   927 					// maskWord is fully masked - skip the pixels
   928 					return;
   929 					}
   930 				if (maskWord == 0xFFFFFFFF)
   931 					{
   932 					// maskWord is fully unmasked - copy the pixels
   933 					while (aLength--)
   934 						{
   935 						*pixelPtr = *aSrcPtr++;
   936 						pixelPtr += pixelPtrInc;
   937 						}
   938 					}
   939 				else
   940 					{
   941 					// maskWord is partially masked - process each pixel
   942 					TUint32 singleBitMask = 1;
   943 					while (aLength--)
   944 						{
   945 						ProcessMaskPixel(aSrcPtr, maskWord, singleBitMask, pixelPtr, pixelPtrInc);
   946 						}
   947 					}
   948 				}
   949 			}
   950 		else
   951 			{
   952 			// Non-optimised path.  UserDisplay mode is different to the true display mode
   953 			while (aLength--)
   954 				{
   955 				TUint32 mask = *(aMaskPtr + (aMaskX >> 5)) & (1 << (aMaskX & 0x1F));
   956 				if (aInvertMask)
   957 					{
   958 					mask = !mask;
   959 					}
   960 				if (mask)
   961 					{
   962 					TRgb pixel(*aSrcPtr);
   963 					MapColorToUserDisplayMode(pixel);
   964 					*pixelPtr = pixel.Value();
   965 					}
   966 				aSrcPtr++;
   967 				aMaskX++;
   968 				pixelPtr += pixelPtrInc;
   969 				}
   970 			}
   971 		return;
   972 		}
   973 	else  // (aSrcFormat==EColor64K)
   974 		{
   975 		const TUint16* srcPtr16 = reinterpret_cast<const TUint16*>(aSrcPtr) + aSrcX;
   976 	
   977 		if ((iUserDispMode==ENone) || (iUserDispMode==EColor16MU))
   978 			{
   979 			const TUint16* lowAdd = Convert16to32bppLow();
   980 			const TUint32* highAdd = Convert16to32bppHigh();
   981 			const TUint32* maskWordPtr = aMaskPtr + (aMaskX >> 5);
   982 			const TInt startBit = aMaskX & 0x1F;
   983 			
   984 			if (startBit)
   985 				{
   986 				// Process initial incomplete mask word
   987 				TUint32 maskWord = *maskWordPtr++;
   988 				maskWord ^= invertWord;
   989 				TInt numPix = Min(aLength, 32 - startBit);  // number of pixels to process from the first word of the mask
   990 				aLength -= numPix;
   991 				
   992 				if (!maskWord)
   993 					{
   994 					// maskWord is fully masked	- skip the pixels
   995 					srcPtr16 += numPix;
   996 					pixelPtr += pixelPtrInc * numPix;
   997 					}
   998 				else if (maskWord == 0xFFFFFFFF)
   999 					{
  1000 					// maskWord is fully unmasked - copy and convert the pixels
  1001 					while (numPix--)
  1002 						{
  1003 						CopyPixel(srcPtr16, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1004 						}
  1005 					}
  1006 				else
  1007 					{
  1008 					// maskWord is partially masked - process each of the pixels
  1009 					TUint32 singleBitMask = 1 << startBit;
  1010 					while (numPix--)
  1011 						{
  1012 						ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1013 						}
  1014 					}
  1015 				}
  1016 			
  1017 			TInt numMaskWords = aLength >> 5;
  1018 			aLength &= 0x1F;
  1019 			while (numMaskWords--)
  1020 				{
  1021 				// Process complete mask words
  1022 				TUint32 maskWord = *maskWordPtr++;
  1023 				maskWord ^= invertWord;
  1024 				
  1025 				if (!maskWord)
  1026 					{
  1027 					// maskWord is fully masked - skip 32 pixels
  1028 					srcPtr16 += 32;
  1029 					pixelPtr += pixelPtrInc << 5;
  1030 					}
  1031 				else if (maskWord == 0xFFFFFFFF)
  1032 					{
  1033 					// maskWord is fully unmasked - copy and convert 32 pixels
  1034 					const TUint32* srcPtr32 = (const TUint32*)srcPtr16;
  1035 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1036 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1037 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1038 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1039 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1040 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1041 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1042 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1043 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1044 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1045 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1046 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1047 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1048 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1049 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1050 					CopyTwoPixels(srcPtr32, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1051 					srcPtr16 = (const TUint16*)srcPtr32;
  1052 					}
  1053 				else
  1054 					{
  1055 					// maskWord is partially masked - process each of the 32 pixels					
  1056 					TUint32 singleBitMask = 1;
  1057 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1058 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1059 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1060 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1061 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1062 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1063 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1064 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1065 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1066 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1067 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1068 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1069 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1070 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1071 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1072 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1073 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1074 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1075 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1076 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1077 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1078 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1079 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1080 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1081 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1082 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1083 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1084 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1085 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1086 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1087 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1088 					ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1089 					}
  1090 				}
  1091 			
  1092 			if (aLength)
  1093 				{
  1094 				// Process final incomplete mask word
  1095 				TUint32 maskWord = *maskWordPtr;		// this will over-read
  1096 				maskWord ^= invertWord;
  1097 				
  1098 				if (!maskWord)
  1099 					{
  1100 					// maskWord is masked - skip the pixels
  1101 					return;
  1102 					}
  1103 					
  1104 				if (maskWord == 0xFFFFFFFF)
  1105 					{
  1106 					// maskWord is fully unmasked - copy and convert the pixels
  1107 					while (aLength--)
  1108 						{
  1109 						CopyPixel(srcPtr16, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1110 						}
  1111 					}
  1112 				else
  1113 					{
  1114 					// maskWord is partially masked - process each of the pixels
  1115 					TUint32 singleBitMask = 1;
  1116 					while (aLength--)
  1117 						{
  1118 						ProcessMaskPixel(srcPtr16, maskWord, singleBitMask, pixelPtr, pixelPtrInc, highAdd, lowAdd);
  1119 						}
  1120 					}
  1121 				}
  1122 			}
  1123 		else
  1124 			{
  1125 			// Non-optimised - expects aMaskPtr untouched and srcPtr16 to be accurate
  1126 			while (aLength--)
  1127 				{
  1128 				TUint32 mask = *(aMaskPtr + (aMaskX >> 5)) & (1 << (aMaskX & 0x1F));
  1129 				if (aInvertMask)
  1130 					{
  1131 					mask = !mask;
  1132 					}
  1133 				if (mask)
  1134 					{
  1135 					const TUint32 src = *srcPtr16;
  1136 					TUint32 color = (src & 0xF800) << 8; // R top 5
  1137 					color |= (src & 0xE000) << 3; // R bottom 3 
  1138 					color |= (src & 0x07E0) << 5; // G top 6
  1139 					color |= (src & 0x0600) >> 1; // G bottom 2
  1140 					color |= (src & 0x001F) << 3; // B top 5
  1141 					color |= (src & 0x001C) >> 2; // B bottom 3
  1142 					TRgb pixel(color);
  1143 					MapColorToUserDisplayMode(pixel);
  1144 					*pixelPtr = pixel.Value();
  1145 					}
  1146 				pixelPtr += pixelPtrInc;
  1147 				srcPtr16++;
  1148 				aMaskX++;
  1149 				}
  1150 			}
  1151 		return;
  1152 		}
  1153 	}
  1154 
  1155 /**
  1156 Implementation for CFbsDrawDevice::GetInterface().
  1157 Retrieves a pointer to a specified interface of CFbsDrawDevice implementation.
  1158 @param aInterfaceId Interface identifier of the interface to be retrieved.
  1159 @param aInterface Address of variable that retrieves the specified interface.
  1160 @return KErrNone If the interface is supported, KErrNotSupported otherwise.
  1161 */
  1162 TInt CDrawUTwentyFourBppBitmap::GetInterface(TInt aInterfaceId, TAny*& aInterface)
  1163 	{
  1164 	aInterface = NULL;
  1165 	TInt ret = KErrNotSupported;
  1166 	
  1167 	switch (aInterfaceId)
  1168 		{
  1169 		case KFastBlitInterfaceID:
  1170 			{
  1171 			aInterface = static_cast<MFastBlit*>(this);
  1172 			ret = KErrNone;
  1173 			break;
  1174 			}
  1175 		default:
  1176 			{
  1177 			return CDrawThirtyTwoBppBitmapCommon::GetInterface(aInterfaceId, aInterface);
  1178 			}
  1179 		}
  1180 		
  1181 	return ret;
  1182 	}
  1183 
  1184 TInt CDrawUTwentyFourBppBitmap::WriteRgbOutlineAndShadow(TInt aX, TInt aY, const TInt aLength,
  1185 														TUint32 aOutlinePenColor, TUint32 aShadowColor,
  1186 														TUint32 aFillColor, const TUint8* aDataBuffer)
  1187 	{
  1188 	DeOrientate(aX,aY);
  1189 	TUint32* pixelPtr = PixelAddress(aX,aY);
  1190 	const TInt pixelPtrInc = PixelAddressIncrement();
  1191 	const TUint8* dataBufferPtrLimit = aDataBuffer + aLength;
  1192 	TInt blendedRedColor;
  1193 	TInt blendedGreenColor;
  1194 	TInt blendedBlueColor;
  1195 	TInt blendedAlpha;
  1196 	TUint8 index = 0;
  1197 	TUint32 finalColor;
  1198 	const TUint16* normTable = PtrTo16BitNormalisationTable();
  1199 
  1200 	//Get red color. Equivalent to TRgb::Red()
  1201 	const TInt redOutlinePenColor = (aOutlinePenColor & 0xff0000) >> 16;
  1202 	const TInt redShadowColor = (aShadowColor & 0xff0000) >> 16;
  1203 	const TInt redFillColor = (aFillColor & 0xff0000) >> 16;
  1204 
  1205 	//Get green color. Equivalent to TRgb::Green()
  1206 	const TInt greenOutlinePenColor = (aOutlinePenColor & 0xff00) >> 8;
  1207 	const TInt greenShadowColor = (aShadowColor & 0xff00) >> 8;
  1208 	const TInt greenFillColor = (aFillColor & 0xff00) >> 8;
  1209 
  1210 	//Get blue color. Equivalent to TRgb::Blue()
  1211 	const TInt blueOutlinePenColor = aOutlinePenColor & 0xff;
  1212 	const TInt blueShadowColor = aShadowColor & 0xff;
  1213 	const TInt blueFillColor = aFillColor & 0xff;
  1214 
  1215 	//Get alpha color. Equivalent to TRgb::Alpha()
  1216 	const TInt alphaOutlinePenColor = aOutlinePenColor >> 24;
  1217 	const TInt alphaShadowColor = aShadowColor >> 24;
  1218 	const TInt alphaFillColor = aFillColor >> 24;
  1219 
  1220 	while (aDataBuffer < dataBufferPtrLimit)
  1221 		{
  1222 		index = *aDataBuffer++;
  1223 		if (255 == FourColorBlendLookup[index][KBackgroundColorIndex])
  1224 			{
  1225 			//background colour
  1226 			//No drawing required
  1227 			}
  1228 		else if (255 == FourColorBlendLookup[index][KFillColorIndex])
  1229 			{
  1230 			//Use fill colour to draw
  1231 			finalColor = aFillColor;
  1232 			AlphaBlendPixelToDest((finalColor | 0xff000000), alphaFillColor, pixelPtr);
  1233 			}
  1234 		else if (255 == FourColorBlendLookup[index][KShadowColorIndex])
  1235 			{
  1236 			//Use shadow colour to draw
  1237 			finalColor = aShadowColor;
  1238 			AlphaBlendPixelToDest((finalColor | 0xff000000), alphaShadowColor, pixelPtr);
  1239 			}
  1240 		else if (255 == FourColorBlendLookup[index][KOutlineColorIndex])
  1241 			{
  1242 			//Use outline colour to draw
  1243 			finalColor = aOutlinePenColor;
  1244 			AlphaBlendPixelToDest((finalColor | 0xff000000), alphaOutlinePenColor, pixelPtr);
  1245 			}
  1246 		else
  1247 			{
  1248 			blendedRedColor = (redOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor + 
  1249 						   		redShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
  1250 						  		redFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
  1251 
  1252 			blendedGreenColor = (greenOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor  + 
  1253 								greenShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
  1254 								greenFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
  1255 
  1256 			blendedBlueColor = (blueOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor  + 
  1257 								blueShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
  1258 								blueFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
  1259 
  1260 			blendedAlpha = (alphaOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] + 
  1261 							alphaShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
  1262 							alphaFillColor * FourColorBlendLookup[index][KFillColorIndex]) >> 8;
  1263 
  1264 			finalColor = PMA2NonPMAPixel((blendedAlpha << 24) | (blendedRedColor << 16) | (blendedGreenColor << 8) | blendedBlueColor, normTable);		
  1265 			AlphaBlendPixelToDest(finalColor | 0xff000000, blendedAlpha, pixelPtr);
  1266 			}
  1267 		pixelPtr += pixelPtrInc;
  1268 		}
  1269 	return KErrNone;
  1270 	}