os/graphics/fbs/fontandbitmapserver/sfbs/BITBMPEX.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1997-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 <f32file.h>
    17 #include <s32file.h>
    18 #include <fbs.h>
    19 #include <bitmap.h>
    20 #include "UTILS.H"
    21 #include <graphics/blendingalgorithms.h>
    22 #include <graphics/lookuptable.h>
    23 //#include "12to16.h"	// lookup table for 12->16 bpp conversion
    24 
    25 #ifdef __ARMCC__
    26 #pragma arm
    27 #pragma O3
    28 #pragma Otime
    29 #endif
    30 
    31 GLREF_C void Panic(TFbsPanic aPanic);
    32 
    33 #define COLOR_VALUE(ScanLinePtr, XPos) (*((ScanLinePtr) + ((XPos) >> 5)) & ( 1 << ((XPos) & 0x1F)))
    34 
    35 
    36 void CBitwiseBitmap::GetScanLineGray2(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TUint32* aScanlinePtr) const
    37 	{
    38 	aLength = Min(aLength,(TInt)((aBuf.MaxLength()) << 3));
    39 	aBuf.SetLength((aLength + 7) >> 3);
    40 
    41 	TUint8* ptr = (TUint8*)aBuf.Ptr();
    42 
    43 	TUint8 mask = 1;
    44 	TInt x = aPixel.iX;
    45 	*ptr=0;
    46 
    47 	if (aDither)
    48 		{
    49 		TBool oddx = aDitherOffset.iX & 1;
    50 		TBool oddy = aDitherOffset.iY & 1;
    51 
    52 		for(TInt count = 0;count < aLength;count++)
    53 			{
    54 			if (!mask)
    55 				{
    56 				mask = 1;
    57 				ptr++;
    58 				*ptr = 0;
    59 				}
    60 			if (HashTo1bpp(GetGrayPixelEx(x,aScanlinePtr),oddx,oddy))
    61 				*ptr |= mask;
    62 			mask <<= 1;
    63 			oddx ^= 1;
    64 			x++;
    65 			}
    66 		}
    67 	else
    68 		{
    69 		for(TInt count = 0;count < aLength;count++)
    70 			{
    71 			if (!mask)
    72 				{
    73 				mask = 1;
    74 				ptr++;
    75 				*ptr = 0;
    76 				}
    77 			if (GetGrayPixelEx(x,aScanlinePtr) > 127)
    78 				*ptr |= mask;
    79 			mask <<= 1;
    80 			x++;
    81 			}
    82 		}
    83 	}
    84 
    85 void CBitwiseBitmap::GetScanLineGray4(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TUint32* aScanlinePtr) const
    86 	{
    87 	aLength = Min(aLength,(TInt)((aBuf.MaxLength())<<2));
    88 	aBuf.SetLength((aLength + 3) >> 2);
    89 
    90 	TUint8* ptr=(TUint8*)aBuf.Ptr();
    91 
    92 	TInt x = aPixel.iX;
    93 	if (iSettings.CurrentDisplayMode() == EGray16 && aDither)
    94 		{
    95 		*ptr=0;
    96 		TInt shift = 0;
    97 		TUint8 col = 0;
    98 		const TInt hasharray[4]={0,3,2,1};
    99 		TInt index = (aDitherOffset.iX&1)+((aDitherOffset.iY&1)<<1);
   100 		for(TInt count=0;count<aLength;count++,shift+=2)
   101 			{
   102 			if (shift==8)
   103 				{
   104 				shift = 0;
   105 				ptr++;
   106 				*ptr = 0;
   107 				}
   108 			col = TUint8(GetGrayPixelEx(x+count,aScanlinePtr) >> 4);
   109 			TInt value=col/5;
   110 			col%=5;
   111 			if (col>2) col--;
   112 			if (hasharray[index]<TInt(col))
   113 				value++;
   114 			value<<=shift;
   115 			*ptr|=value;
   116 			index^=1;
   117 			}
   118 		}
   119 	else
   120 		{
   121 		TUint8* ptrLimit = ptr + ((aLength + 3) >> 2);
   122 		while (ptr < ptrLimit)
   123 			{
   124 			TUint8 pixelGrayShade = TUint8(GetGrayPixelEx(x++,aScanlinePtr) >> 6);
   125 			pixelGrayShade |= TUint8((GetGrayPixelEx(x++,aScanlinePtr) >> 4) & 0x0c);
   126 			pixelGrayShade |= TUint8((GetGrayPixelEx(x++,aScanlinePtr) >> 2) & 0x30);
   127 			pixelGrayShade |= TUint8(GetGrayPixelEx(x++,aScanlinePtr) & 0xc0);
   128 			*ptr++ = pixelGrayShade;
   129 			}
   130 		}
   131 	}
   132 
   133 void CBitwiseBitmap::GetScanLineGray16(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   134 	{
   135 	aLength=Min(aLength,(TInt)(aBuf.MaxLength()<<1));
   136 	aBuf.SetLength((aLength + 1) >> 1);
   137 
   138 	TUint8* ptr = (TUint8*)aBuf.Ptr();
   139 	TUint8* ptrLimit = ptr + aBuf.Length();
   140 	TInt x = aPixel.iX;
   141 
   142 	if(iHeader.iBitsPerPixel == 1)
   143 		{
   144 		while (ptr < ptrLimit)
   145 			{
   146 			TUint8 pixelGrayShade = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0x0F : 0);
   147 			x++;
   148 			pixelGrayShade |= TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xF0 : 0);
   149 			x++;
   150 			*ptr++ = pixelGrayShade;
   151 			}
   152 		}
   153 	else
   154 		{
   155 		while (ptr < ptrLimit)
   156 			{
   157 			TUint8 pixelGrayShade = TUint8(GetGrayPixelEx(x++,aScanlinePtr) >> 4);
   158 			pixelGrayShade |= GetGrayPixelEx(x++,aScanlinePtr) & 0xf0;
   159 			*ptr++ = pixelGrayShade;
   160 			}
   161 		}
   162 	}
   163 
   164 void CBitwiseBitmap::GetScanLineGray256(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   165 	{
   166 	aLength = Min(aLength,aBuf.MaxLength());
   167 	aBuf.SetLength(aLength);
   168 
   169 	TUint8* ptr = (TUint8*)aBuf.Ptr();
   170 	TUint8* ptrLimit = ptr + aLength;
   171 	TInt xCoord = aPixel.iX;
   172 
   173 	if(iHeader.iBitsPerPixel == 1)
   174 		{
   175 		while (ptr < ptrLimit)
   176 			{
   177 			*ptr++ = TUint8(COLOR_VALUE(aScanlinePtr, xCoord) ? 0xFF : 0);
   178 			xCoord++;
   179 			}
   180 		}
   181 	else
   182 		{
   183 		while (ptr < ptrLimit)
   184 			*ptr++ = GetGrayPixelEx(xCoord++,aScanlinePtr);
   185 		}
   186 	}
   187 
   188 void CBitwiseBitmap::GetScanLineColor16(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   189 	{
   190 	aLength=Min(aLength,(TInt)(aBuf.MaxLength()<<1));
   191 	aBuf.SetLength((aLength + 1) >> 1);
   192 
   193 	TUint8* ptr = (TUint8*)aBuf.Ptr();
   194 	TUint8* ptrLimit = ptr + aBuf.Length();
   195 	TInt x = aPixel.iX;
   196 
   197 	if(iHeader.iBitsPerPixel == 1)
   198 		{
   199 		while (ptr < ptrLimit)
   200 			{
   201 			TUint8 pixelGrayShade = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0x0F : 0);
   202 			x++;
   203 			pixelGrayShade |= TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xF0 : 0);
   204 			x++;
   205 			*ptr++ = pixelGrayShade;
   206 			}
   207 		}
   208 	else
   209 		{
   210 		while (ptr < ptrLimit)
   211 			{
   212 			TUint8 pixelGrayShade = TUint8(GetRgbPixelEx(x++,aScanlinePtr).Color16());
   213 			pixelGrayShade |= GetRgbPixelEx(x++,aScanlinePtr).Color16() << 4;
   214 			*ptr++ = pixelGrayShade;
   215 			}
   216 		}
   217 	}
   218 
   219 void CBitwiseBitmap::GetScanLineColor256(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   220 	{
   221 	aLength = Min(aLength,aBuf.MaxLength());
   222 	aBuf.SetLength(aLength);
   223 
   224 	TUint8* ptr = (TUint8*)aBuf.Ptr();
   225 	TUint8* ptrLimit = ptr + aLength;
   226 	TInt xCoord = aPixel.iX;
   227 
   228 	if(iHeader.iBitsPerPixel == 1)
   229 		{
   230 		while (ptr < ptrLimit)
   231 			{
   232 			*ptr++ = TUint8(COLOR_VALUE(aScanlinePtr, xCoord) ? 0xFF : 0);
   233 			xCoord++;
   234 			}
   235 		}
   236 	else
   237 		{
   238 		while (ptr < ptrLimit)
   239 			*ptr++ = TUint8(GetRgbPixelEx(xCoord++,aScanlinePtr).Color256());
   240 		}
   241 	}
   242 
   243 void CBitwiseBitmap::GetScanLineColor4K(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   244 	{
   245 	aLength = Min(aLength,aBuf.MaxLength() >> 1);
   246 	aBuf.SetLength(aLength << 1);
   247 
   248 	TUint16* ptr = (TUint16*)aBuf.Ptr();
   249 	const TUint16* ptrLimit = ptr + aLength;
   250 	TInt x = aPixel.iX;
   251 
   252 	if(iHeader.iBitsPerPixel == 1)
   253 		{
   254 		while (ptr < ptrLimit)
   255 			{
   256 			*ptr++ = TUint16(COLOR_VALUE(aScanlinePtr, x) ? 0x0FFF : 0);
   257 			x++;
   258 			}
   259 		}
   260 	else
   261 		{
   262 		while (ptr < ptrLimit)
   263 			*ptr++ = TUint16(GetRgbPixelEx(x++,aScanlinePtr)._Color4K());
   264 		}
   265 	}
   266 
   267 void CBitwiseBitmap::GetScanLineColor64K(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   268 	{
   269 	aLength = Min(aLength,aBuf.MaxLength() >> 1);
   270 	aBuf.SetLength(aLength << 1);
   271 
   272 	TUint16* ptr = (TUint16*)aBuf.Ptr();
   273 	TUint16* ptrLimit = ptr + aLength;
   274 	TInt x = aPixel.iX;
   275 
   276 	if(iHeader.iBitsPerPixel == 1)
   277 		{
   278 		while (ptr < ptrLimit)
   279 			{
   280 			*ptr++ = TUint16(COLOR_VALUE(aScanlinePtr, x) ? 0xFFFF : 0);
   281 			x++;
   282 			}
   283 		}
   284 	else if(iHeader.iBitsPerPixel == 12)
   285 		{
   286 /*
   287 		// use lookup table for 12->16 conversion
   288 		TUint16* pixel4K = ((TUint16*) aScanlinePtr) + x;
   289 		while(ptr < ptrLimit)
   290 			{
   291 			// this takes the 12 bit value, this is a number between 0 and 4095,
   292 			// and looks up its corrosponding 16 bit value in the lookup table.
   293 			// the colour should be identical, and but just in a different format
   294 			// see below for an explaination of 12 & 16 bit colour values
   295 			*ptr++ = K12to16LUT[*pixel4K++];
   296 			}
   297 */
   298 /*		This code uses logic rather than a lookup table
   299 		to convert from 12->16 bpp and can be used instead of the above code
   300 		if the 8k the lookup table uses becomes an issue
   301 
   302 		12 bit colour
   303 		-------------
   304 		The 12 bit colour format uses 4 bits for the red, green and blue values.
   305 		The colour is stored as a word with the most significant 4 bits having a
   306 		value of zero.
   307 		i.e. 0000RRRR GGGGBBBB where R,G & B represent single bits in the word.
   308 
   309 		The code below labeled 'conversion of 4k colour...' changes the colour from
   310 		16 bit to 32 bit where each colour nibble in the 16 bit version is changed
   311 		to a byte in the 32 bit version e.g.
   312 		0000RRRR GGGGBBBB -> 00000000 RRRRRRRR GGGGGGGG BBBBBBBB
   313 
   314 
   315 		16 bit colour
   316 		-------------
   317 		The 16 bit colour format uses all 16 bits to represent the required colour.
   318 		There are two possible 16 bit formats 5-5-5 and 5-6-5.
   319 		Symbian uses the 5-6-5 format, with this all 16 bits are used to make the colour
   320 		giving a possible value between 0..65535.  The RGB components are divided up
   321 		as follows RRRR RGGG GGGB BBBB i.e. 5 bits for red and blue, and 6 for green.
   322 
   323 		The code below labeled 'conversion to 64k' converts the colour from a 16 bit
   324 		0000 RRRR GGGG BBBB -> RRRR RGGG GGGB BBBB format.
   325 */
   326 		register TUint16* pixel4K = ((TUint16*) aScanlinePtr) + x;
   327 		while (ptr < ptrLimit)
   328 			{
   329 			// conversion of 4k colour from 16 to 32 bits
   330 			// this changes from a 16 to 32 bit value while keeping colour unchanged
   331 			register TUint16 pixelVal = *pixel4K++;
   332 			register TUint32 value32 = ((pixelVal & 0x0f00) >> 8) |
   333 									   ((pixelVal & 0x00f0) << 4) |
   334 									   ((pixelVal & 0x000f) << 16);
   335 			value32 |= (value32 << 4);
   336 			// conversion to 64k (RRRR RGGG GGGB BBBB)
   337 			// this will make the change from (16 bit) 4-4-4 bpp to 5-6-5 bpp format
   338 			register TUint32 color64K = ((value32 & 0x000000f8) << 8) |
   339 										((value32 & 0x0000fc00) >> 5) |
   340 										((value32 & 0x00f80000) >> 19);
   341 			// store new colour value
   342 			*ptr++ = static_cast <TUint16> (color64K);
   343 			}
   344 		}
   345 	else
   346 		{
   347 		while (ptr < ptrLimit)
   348 			*ptr++ = TUint16(GetRgbPixelEx(x++,aScanlinePtr)._Color64K());
   349 		}
   350 	}
   351 
   352 void CBitwiseBitmap::GetScanLineColor16M(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   353 	{
   354 	aLength = Min(aLength,aBuf.MaxLength() / 3);
   355 	aBuf.SetLength(aLength * 3);
   356 
   357 	TUint8* ptr = (TUint8*)aBuf.Ptr();
   358 	TUint8* ptrLimit = ptr + (aLength * 3);
   359 	TInt x = aPixel.iX;
   360 
   361 	if(iHeader.iBitsPerPixel == 1)
   362 		{
   363 		while (ptr < ptrLimit)
   364 			{
   365 			const TUint8 color = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xFF : 0);
   366 			*ptr++ = color;
   367 			*ptr++ = color;
   368 			*ptr++ = color;
   369 			x++;
   370 			}
   371 		}
   372 	else
   373 		{
   374 		GetRgbPixelExMany16M(aPixel.iX,aScanlinePtr,ptr,aLength);
   375 		}
   376 	}
   377 
   378 void CBitwiseBitmap::GetScanLineColor16MU(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   379 	{
   380 	aLength = Min(aLength,aBuf.MaxLength() >> 2);
   381 	aBuf.SetLength(aLength << 2);
   382 
   383 	TUint32* ptr = (TUint32*)aBuf.Ptr();
   384 
   385 	GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength);
   386 	}
   387 
   388 void CBitwiseBitmap::GetScanLineColor16MA(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   389 	{
   390 	aLength = Min(aLength,aBuf.MaxLength() >> 2);
   391 	aBuf.SetLength(aLength << 2);
   392 
   393 	TUint32* ptr = (TUint32*)aBuf.Ptr();
   394 	GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength);
   395 	}
   396 
   397 /**
   398 Get the scanline data into the destination buffer in the EColor16MAP format.
   399 @param	aDestBuf - destination buffer
   400 @param	aPixel - the start position of the scanline.
   401 @param	aLength - scanline length, as word length
   402 @param	aScanlinePtr - scanline pointer
   403 */
   404 void CBitwiseBitmap::GetScanLineColor16MAP(TDes8& aDestBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   405 	{
   406 	aLength = Min(aLength, aDestBuf.MaxLength() >> 2);
   407 	aDestBuf.SetLength(aLength << 2);
   408 	TUint32* ptr = (TUint32*)aDestBuf.Ptr();
   409 	GetRgbPixelExMany16MAP(aPixel.iX,aScanlinePtr,ptr,aLength);
   410 	}
   411 
   412 
   413 void CBitwiseBitmap::GetScanLineColorRgb(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
   414 	{
   415 	aLength = Min(aLength,aBuf.MaxLength() / sizeof(TRgb));
   416 	aBuf.SetLength(aLength * sizeof(TRgb));
   417 
   418 	TUint32* ptr = (TUint32*)aBuf.Ptr();
   419 	GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength);
   420 	}
   421 
   422 void CBitwiseBitmap::GetScanLineExBits(TDes8& aBuf,TInt aX,TInt aLength,TUint32* aScanlinePtr) const
   423 	{
   424 	TInt bitshift = 1;
   425 	TInt pixelsPerWord = 8;
   426 	TInt roundingmask = ~0x7;
   427 	TInt logbpp = 2;
   428 	TInt roundupfactor = 1;
   429 	const TDisplayMode displayMode = iSettings.CurrentDisplayMode();
   430 
   431 	switch(displayMode)
   432 		{
   433 		case EGray16:
   434 		case EColor16:
   435 			break; // set by default
   436 		case EGray4:
   437 			{
   438 			bitshift = 2;
   439 			pixelsPerWord = 16;
   440 			roundingmask = ~0xf;
   441 			logbpp = 1;
   442 			roundupfactor = 3;
   443 			break;
   444 			}
   445 		case EGray2:
   446 			{
   447 			bitshift = 3;
   448 			pixelsPerWord = 32;
   449 			roundingmask = ~0x1f;
   450 			logbpp = 0;
   451 			roundupfactor = 7;
   452 			break;
   453 			}
   454 		default:
   455 			Panic(EFbsBitmapInvalidMode);
   456 		}
   457 
   458 	aLength = Min(aLength,aBuf.MaxLength() << bitshift);
   459 	aBuf.SetLength((aLength + roundupfactor) >> bitshift);
   460 
   461 	TUint32* ptr = (TUint32*)aBuf.Ptr(); // guaranteed to be word aligned by the calling function
   462 	TInt startlong = aX & roundingmask;
   463 	TInt finishlong = (aX + aLength + pixelsPerWord - 1) & roundingmask;
   464 	bitshift += 2; // Convert pixels per byte shift to pixels per word shift
   465 	TUint32* wordptr = aScanlinePtr + (startlong >> bitshift);
   466 	TInt wordLength = (finishlong - startlong) >> bitshift;
   467 	TUint32* wordptrLimit = wordptr + wordLength;
   468 
   469 	const TInt destinationWords = Min(aBuf.MaxLength() >> 2,wordLength);
   470 	TUint32* ptrlimit = ptr + destinationWords;
   471 
   472 	TInt offset = (aX - startlong) << logbpp;
   473 
   474 	if (offset)
   475 		{
   476 		TInt offsetextra = 32-offset;
   477 		TUint32 data = *wordptr++;
   478 		data >>= offset;
   479 
   480 		while (ptr < ptrlimit - 1)
   481 			{
   482 			TUint32 tmp = *wordptr++;
   483 			data |= tmp << offsetextra;
   484 			*ptr++ = data;
   485 			data = tmp >> offset;
   486 			}
   487 
   488 		if (wordptr < wordptrLimit)
   489 			*ptr = data | (*wordptr << offsetextra);
   490 		else
   491 			*ptr = data;
   492 		}
   493 	else
   494 		{
   495 		while (ptr < ptrlimit)
   496 			*ptr++ = *wordptr++;
   497 
   498 		// if the buffer isn't a whole number of words long,
   499 		// we need to copy the remaining bytes
   500 		const TInt bytesRemaining = aBuf.Length() - (destinationWords * sizeof(TUint32));
   501 		if (bytesRemaining > 0)
   502 			Mem::Copy(ptr,wordptr,bytesRemaining);
   503 
   504 		}
   505 	}
   506 
   507 void CBitwiseBitmap::GetScanLineExBytes(TDes8& aBuf,TInt aX,TInt aLength,TUint32* aScanlinePtr) const
   508 	{
   509 	TInt numberOfBytesToCopy = 0;
   510 	TUint8* ptr = (TUint8*)aScanlinePtr;
   511 	TDisplayMode displayMode = iSettings.CurrentDisplayMode();
   512 	switch(displayMode)
   513 		{
   514 		case EGray256:
   515 		case EColor256:
   516 			{
   517 			aLength = Min(aLength,aBuf.MaxLength());
   518 			numberOfBytesToCopy = aLength;
   519 			ptr += aX;
   520 			break;
   521 			}
   522 		case EColor4K:
   523 		case EColor64K:
   524 			{
   525 			aLength = Min(aLength,aBuf.MaxLength() / 2);
   526 			numberOfBytesToCopy = aLength * 2;
   527 			ptr += (aX << 1);
   528 			break;
   529 			}
   530 		case EColor16M:
   531 			{
   532 			aLength = Min(aLength,aBuf.MaxLength() / 3);
   533 			numberOfBytesToCopy = aLength * 3;
   534 			ptr += (aX * 3);
   535 			break;
   536 			}
   537 		case EColor16MU:
   538 		case EColor16MA:
   539 		case EColor16MAP:
   540 			{
   541 			aLength = Min(aLength,aBuf.MaxLength() / 4);
   542 			numberOfBytesToCopy = aLength * 4;
   543 			ptr += (aX * 4);
   544 			break;
   545 			}
   546 		default:
   547 			Panic(EFbsBitmapInvalidMode);
   548 		}
   549 
   550 	aBuf.SetLength(numberOfBytesToCopy);
   551 
   552 	Mem::Copy((TAny*)aBuf.Ptr(),ptr,numberOfBytesToCopy);
   553 	}
   554 
   555 void CBitwiseBitmap::DoStretchScanLine(TDes8& aBuf,TInt x,TInt y,TInt aClipStrchX,
   556 	TInt aClipStrchLen,TInt aStretchLength,TInt aOrgX,TInt aOrgLen,
   557 	const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase,
   558 	TLineScanningPosition& aLineScanningPosition) const
   559 	{
   560 	TInt lastValue = 0;
   561 	TUint32* bufptr=(TUint32*)((TInt)(&aBuf[0]+3)&~3);
   562 	TUint32* buflimit=bufptr;
   563 	TUint32* slptr=NULL;
   564 	TPoint pixel(aOrgX,y);
   565 	const TDisplayMode displayMode = iSettings.CurrentDisplayMode();
   566 	GetScanLinePtr(slptr, aOrgLen, pixel,aBase, aLineScanningPosition);
   567 	if (!slptr)
   568 		{
   569 		WhiteFill((TUint8*)aBuf.Ptr(),aBuf.MaxLength(),displayMode);
   570 		return;
   571 		}
   572 
   573 	TInt lastcoord=-1;
   574 	TLinearDDA stretchmap;
   575 	TPoint coordmap(aOrgX,0);
   576 	stretchmap.Construct(coordmap,coordmap+TPoint(aOrgLen,aStretchLength),TLinearDDA::ELeft);
   577 	coordmap.iY=aClipStrchX;
   578 	if (aClipStrchX>0) stretchmap.JumpToYCoord(coordmap.iX,coordmap.iY);
   579 	else stretchmap.SingleStep(coordmap);
   580 	switch(aDispMode)
   581 		{
   582 		case EGray4:
   583 			{
   584 			aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<4));
   585 			aBuf.SetLength((aClipStrchLen+3)>>2);
   586 			buflimit+=(aBuf.Length()+3)>>2;
   587 			if (displayMode == EGray16)
   588 				{
   589 				TInt index=((aDitherOffset.iY&1)<<1)+((aDitherOffset.iX+x)&1);
   590 				while(bufptr<buflimit)
   591 					{
   592 					TInt shift=0;
   593 					*bufptr=0;
   594 					while(shift<32)
   595 						{
   596 						if (coordmap.iX>lastcoord)
   597 							{
   598 							lastValue=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
   599 							lastcoord=coordmap.iX;
   600 							}
   601 						*bufptr|=(lastValue<<shift);
   602 						index^=1;
   603 						shift+=2;
   604 						if (stretchmap.SingleStep(coordmap)) break;
   605 						}
   606 					bufptr++;
   607 					}
   608 				}
   609 			else
   610 				{
   611 				while (bufptr < buflimit)
   612 					{
   613 					TInt shift = 0;
   614 					*bufptr = 0;
   615 					while (shift < 32)
   616 						{
   617 						if (coordmap.iX>lastcoord)
   618 							{
   619 							lastValue = GetGrayPixelEx(coordmap.iX,slptr) >> 6;
   620 							lastcoord = coordmap.iX;
   621 							}
   622 						*bufptr |= (lastValue << shift);
   623 						shift += 2;
   624 						if (stretchmap.SingleStep(coordmap)) break;
   625 						}
   626 					bufptr++;
   627 					}
   628 				}
   629 			break;
   630 			}
   631 		case EGray16:
   632 			{
   633 			aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<3));
   634 			aBuf.SetLength((aClipStrchLen+1)>>1);
   635 			buflimit+=(aBuf.Length()+3)>>2;
   636 			while(bufptr<buflimit)
   637 				{
   638 				TInt shift=0;
   639 				*bufptr=0;
   640 				while(shift<32)
   641 					{
   642 					if (coordmap.iX>lastcoord)
   643 						{
   644 						lastValue = GetGrayPixelEx(coordmap.iX,slptr) >> 4;
   645 						lastcoord=coordmap.iX;
   646 						}
   647 					*bufptr |= lastValue << shift;
   648 					shift+=4;
   649 					if (stretchmap.SingleStep(coordmap)) break;
   650 					}
   651 				bufptr++;
   652 				}
   653 			break;
   654 			}
   655 		case EColor16:
   656 			{
   657 			aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<3));
   658 			aBuf.SetLength((aClipStrchLen+1)>>1);
   659 			buflimit+=(aBuf.Length()+3)>>2;
   660 			while(bufptr<buflimit)
   661 				{
   662 				TInt shift=0;
   663 				*bufptr=0;
   664 				while(shift<32)
   665 					{
   666 					if (coordmap.iX>lastcoord)
   667 						{
   668 						lastValue = GetRgbPixelEx(coordmap.iX,slptr).Color16();
   669 						lastcoord = coordmap.iX;
   670 						}
   671 					*bufptr |= lastValue << shift;
   672 					shift+=4;
   673 					if (stretchmap.SingleStep(coordmap)) break;
   674 					}
   675 				bufptr++;
   676 				}
   677 			break;
   678 			}
   679 		case EGray256:
   680 			{
   681 			aClipStrchLen = Min(aClipStrchLen,(TInt)(aBuf.MaxLength() & ~3));
   682 			aBuf.SetLength(aClipStrchLen);
   683 			buflimit += (aBuf.Length() + 3) >> 2;
   684 
   685 			while (bufptr < buflimit)
   686 				{
   687 				TInt shift=0;
   688 				*bufptr=0;
   689 				while(shift<32)
   690 					{
   691 					if (coordmap.iX>lastcoord)
   692 						{
   693 						lastValue = GetGrayPixelEx(coordmap.iX,slptr);
   694 						lastcoord=coordmap.iX;
   695 						}
   696 					*bufptr |= lastValue << shift;
   697 					shift += 8;
   698 					if (stretchmap.SingleStep(coordmap))
   699 						break;
   700 					}
   701 				bufptr++;
   702 				}
   703 			break;
   704 			}
   705 		case EColor256:
   706 			{
   707 			aClipStrchLen = Min(aClipStrchLen,(TInt)(aBuf.MaxLength() & ~3));
   708 			aBuf.SetLength(aClipStrchLen);
   709 			buflimit += (aBuf.Length() + 3) >> 2;
   710 
   711 			while (bufptr < buflimit)
   712 				{
   713 				TInt shift=0;
   714 				*bufptr=0;
   715 				while(shift<32)
   716 					{
   717 					if (coordmap.iX>lastcoord)
   718 						{
   719 						lastValue = TUint8(GetRgbPixelEx(coordmap.iX,slptr).Color256());
   720 						lastcoord = coordmap.iX;
   721 						}
   722 					*bufptr |= lastValue << shift;
   723 					shift += 8;
   724 					if (stretchmap.SingleStep(coordmap))
   725 						break;
   726 					}
   727 				bufptr++;
   728 				}
   729 			break;
   730 			}
   731 		case EColor4K:
   732 			{
   733 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1);
   734 			aBuf.SetLength(aClipStrchLen << 1);
   735 			buflimit += (aBuf.Length() + 3) >> 2;
   736 
   737 			while (bufptr < buflimit)
   738 				{
   739 				if (coordmap.iX>lastcoord)
   740 					{
   741 					lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color4K();
   742 					lastcoord=coordmap.iX;
   743 					}
   744 				*bufptr = lastValue;
   745 				if (stretchmap.SingleStep(coordmap))
   746 					break;
   747 				if (coordmap.iX>lastcoord)
   748 					{
   749 					lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color4K();
   750 					lastcoord=coordmap.iX;
   751 					}
   752 				*bufptr |= lastValue << 16;
   753 				if (stretchmap.SingleStep(coordmap))
   754 					break;
   755 				bufptr++;
   756 				}
   757 			break;
   758 			}
   759 		case EColor64K:
   760 			{
   761 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1);
   762 			aBuf.SetLength(aClipStrchLen << 1);
   763 			buflimit += (aBuf.Length() + 3) >> 2;
   764 
   765 			while (bufptr < buflimit)
   766 				{
   767 				if (coordmap.iX>lastcoord)
   768 					{
   769 					lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color64K();
   770 					lastcoord=coordmap.iX;
   771 					}
   772 				*bufptr = lastValue;
   773 				if (stretchmap.SingleStep(coordmap))
   774 					break;
   775 				if (coordmap.iX>lastcoord)
   776 					{
   777 					lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color64K();
   778 					lastcoord=coordmap.iX;
   779 					}
   780 				*bufptr |= lastValue << 16;
   781 				if (stretchmap.SingleStep(coordmap))
   782 					break;
   783 				bufptr++;
   784 				}
   785 			break;
   786 			}
   787 		case EColor16M: // Destination Mode
   788 			{
   789 			// Optimisation: Both of conditions on 32bpp and 24bpp were added to avoid to use
   790 			// GetRgbPixelEx() for each pixel
   791 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / 3);
   792 			aBuf.SetLength(aClipStrchLen * 3);
   793 			TUint8* ptr = (TUint8*)bufptr;
   794 			TUint8* ptrLimit = ptr + aBuf.Length();
   795 
   796 			if (iHeader.iBitsPerPixel == 32) // 32bpp source image => color
   797 				{
   798 				TInt lastColor = 0;
   799 				if(displayMode == EColor16MAP)
   800 					{
   801 					const TUint16* normTable = PtrTo16BitNormalisationTable();
   802 					while (ptr < ptrLimit)
   803 						{
   804 						if (coordmap.iX > lastcoord)
   805 							{
   806 							lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable);
   807 							lastcoord = coordmap.iX;
   808 							}
   809 						*ptr++ = TUint8(lastColor);
   810 						*ptr++ = TUint8(lastColor >> 8);
   811 						*ptr++ = TUint8(lastColor >> 16);
   812 						if (stretchmap.SingleStep(coordmap))
   813 							break;
   814 						}
   815 					}
   816 				else{
   817 					while (ptr < ptrLimit)
   818 						{
   819 						if (coordmap.iX > lastcoord)
   820 							{
   821 							lastColor = *(slptr + coordmap.iX);
   822 							lastcoord = coordmap.iX;
   823 							}
   824 						*ptr++ = TUint8(lastColor);
   825 						*ptr++ = TUint8(lastColor >> 8);
   826 						*ptr++ = TUint8(lastColor >> 16);
   827 						if (stretchmap.SingleStep(coordmap))
   828 							break;
   829 						}
   830 					}
   831 				}
   832 			else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color
   833 				{
   834 				TInt lastColor = 0;
   835 				while (ptr < ptrLimit)
   836 					{
   837 					if (coordmap.iX > lastcoord)
   838 						{
   839 						TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3;
   840 						lastColor = TUint8(*scanLineBytePointer);
   841 						scanLineBytePointer++;
   842 						lastColor |= TUint8(*scanLineBytePointer) << 8;
   843 						scanLineBytePointer++;
   844 						lastColor |= TUint8(*scanLineBytePointer) << 16;
   845 						lastcoord = coordmap.iX;
   846 						}
   847 					*ptr++ = TUint8(lastColor);
   848 					*ptr++ = TUint8(lastColor >> 8);
   849 					*ptr++ = TUint8(lastColor >> 16);
   850 					if (stretchmap.SingleStep(coordmap))
   851 						break;
   852 					}
   853 				}
   854 			else
   855 				{
   856 				TRgb lastColor;
   857 				while (ptr < ptrLimit)
   858 					{
   859 					if (coordmap.iX>lastcoord)
   860 						{
   861 						lastColor = GetRgbPixelEx(coordmap.iX,slptr);
   862 						lastcoord=coordmap.iX;
   863 						}
   864 					TInt color16M = lastColor._Color16M();
   865 					*ptr++ = TUint8(color16M);
   866 					*ptr++ = TUint8(color16M >> 8);
   867 					*ptr++ = TUint8(color16M >> 16);
   868 					if (stretchmap.SingleStep(coordmap))
   869 						break;
   870 					}
   871 				}
   872 			break;
   873 			}
   874 		case ERgb:
   875 			{
   876 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / sizeof(TRgb));
   877 			aBuf.SetLength(aClipStrchLen * sizeof(TRgb));
   878 			TRgb* pixelPtr = (TRgb*)bufptr;
   879 			TRgb* pixelPtrLimit = pixelPtr + aClipStrchLen;
   880 			TRgb lastColor;
   881 
   882 			while (pixelPtr < pixelPtrLimit)
   883 				{
   884 				if (coordmap.iX > lastcoord)
   885 					{
   886 					lastColor = GetRgbPixelEx(coordmap.iX,slptr);
   887 					lastcoord = coordmap.iX;
   888 					}
   889 				*pixelPtr++ = lastColor;
   890 				if (stretchmap.SingleStep(coordmap))
   891 					break;
   892 				}
   893 			break;
   894 			}
   895 		case EColor16MU: // Destination Mode
   896 			{
   897 			// Optimisation: The condition 32bpp was added to avoid to use
   898 			//GetRgbPixelEx() for each pixel (construction of a TRgb object each time)
   899 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2);
   900 			aBuf.SetLength(aClipStrchLen << 2);
   901 			TInt32* pixelPtr = (TInt32*)bufptr;
   902 			TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen;
   903 
   904 			if (iHeader.iBitsPerPixel == 32) //32bpp source image => color
   905 				{
   906 				TInt lastColor = 0;
   907 				if(displayMode == EColor16MAP)
   908 					{
   909 					const TUint16* normTable = PtrTo16BitNormalisationTable();
   910 					while (pixelPtr < pixelPtrLimit)
   911 						{
   912 						if (coordmap.iX > lastcoord)
   913 							{
   914 							lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable);
   915 							lastcoord = coordmap.iX;
   916 							}
   917 						*pixelPtr++ = (lastColor | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order
   918 						if (stretchmap.SingleStep(coordmap))
   919 							break;
   920 						}
   921 					}
   922 				else{
   923 					while (pixelPtr < pixelPtrLimit)
   924 						{
   925 						if (coordmap.iX > lastcoord)
   926 							{
   927 							lastColor = *(slptr + coordmap.iX);
   928 							lastcoord = coordmap.iX;
   929 							}
   930 						*pixelPtr++ = (lastColor | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order
   931 						if (stretchmap.SingleStep(coordmap))
   932 							break;
   933 						}
   934 					}
   935 				}
   936 				
   937 			else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color
   938 				{
   939 				TInt lastColor = 0;
   940 				while (pixelPtr < pixelPtrLimit)
   941 					{
   942 					if (coordmap.iX > lastcoord)
   943 						{
   944 						TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3;
   945 						lastColor = TUint8(*scanLineBytePointer);
   946 						scanLineBytePointer++;
   947 						lastColor |= TUint8(*scanLineBytePointer) << 8;
   948 						scanLineBytePointer++;
   949 						lastColor |= TUint8(*scanLineBytePointer) << 16;
   950 						lastcoord = coordmap.iX;
   951 						}
   952 					*pixelPtr++ = (lastColor | 0xff000000);
   953 					if (stretchmap.SingleStep(coordmap))
   954 						break;
   955 					}
   956 				}
   957 			else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color
   958 				{
   959 				TInt lastColor = 0;
   960 				while (pixelPtr < pixelPtrLimit)
   961 					{
   962 					if (coordmap.iX > lastcoord)
   963 						{
   964 						TUint rawColor = *(((TUint16*)slptr) + coordmap.iX);
   965 						TInt red = (rawColor   & 0xF800)>>8;
   966 						red += red>>5;
   967 						TInt green = (rawColor & 0x07E0)>>3;
   968 						green += green>>6;
   969 						TInt blue = (rawColor  & 0x001F)<<3;
   970 						blue += blue>>5;
   971 						lastColor = 0xff000000 | (red << 16) | (green << 8) | blue;
   972 						lastcoord = coordmap.iX;
   973 						}
   974 					*pixelPtr++ = lastColor;
   975 					if (stretchmap.SingleStep(coordmap))
   976 						break;
   977 					}
   978 				}
   979 			else
   980 				{
   981 				TRgb lastColor;
   982 				while (pixelPtr < pixelPtrLimit)
   983 					{
   984 					if (coordmap.iX > lastcoord)
   985 						{
   986 						lastColor = GetRgbPixelEx(coordmap.iX,slptr);
   987 						lastcoord = coordmap.iX;
   988 						}
   989 					*pixelPtr++ = (lastColor._Color16MU() | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order
   990 					if (stretchmap.SingleStep(coordmap))
   991 						break;
   992 					}
   993 				}
   994 			break;
   995 			}
   996 		case EColor16MA:
   997 			{
   998 			// Optimisation: The condition 32bpp was added to avoid to use
   999 			// GetRgbPixelEx() for each pixel (construction of a TRgb object each time)
  1000 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2);
  1001 			aBuf.SetLength(aClipStrchLen << 2);
  1002 			TInt32* pixelPtr = (TInt32*)bufptr;
  1003 			TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen;
  1004 			const TUint16* normTable = PtrTo16BitNormalisationTable();
  1005 			if (iHeader.iBitsPerPixel == 32) //32bpp source image => color
  1006 				{
  1007 				TInt lastColor = 0;
  1008 				if(displayMode == EColor16MAP)
  1009 					{
  1010 					while (pixelPtr < pixelPtrLimit)
  1011 						{
  1012 						if (coordmap.iX > lastcoord)
  1013 							{
  1014 							lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable);
  1015 							lastcoord = coordmap.iX;
  1016 							}
  1017 						*pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order
  1018 						if (stretchmap.SingleStep(coordmap))
  1019 							break;
  1020 						}
  1021 					}
  1022 				else
  1023 					{
  1024 					while (pixelPtr < pixelPtrLimit)
  1025 						{
  1026 						if (coordmap.iX > lastcoord)
  1027 							{
  1028 							lastColor = *(slptr + coordmap.iX);
  1029 							lastcoord = coordmap.iX;
  1030 							}
  1031 						*pixelPtr++ = lastColor;
  1032 						if (stretchmap.SingleStep(coordmap))
  1033 								break;
  1034 						}
  1035 					}
  1036 				}
  1037 			else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color
  1038 				{
  1039 				TInt lastColor = 0;
  1040 				while (pixelPtr < pixelPtrLimit)
  1041 					{
  1042 					if (coordmap.iX > lastcoord)
  1043 						{
  1044 						TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3;
  1045 						lastColor = TUint8(*scanLineBytePointer);
  1046 						scanLineBytePointer++;
  1047 						lastColor |= TUint8(*scanLineBytePointer) << 8;
  1048 						scanLineBytePointer++;
  1049 						lastColor |= TUint8(*scanLineBytePointer) << 16;
  1050 						lastcoord = coordmap.iX;
  1051 						}
  1052 					*pixelPtr++ = (lastColor | 0xff000000);
  1053 					if (stretchmap.SingleStep(coordmap))
  1054 						break;
  1055 					}
  1056 				}
  1057 			else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color
  1058 				{
  1059 				TInt lastColor = 0;
  1060 				while (pixelPtr < pixelPtrLimit)
  1061 					{
  1062 					if (coordmap.iX > lastcoord)
  1063 						{
  1064 						TUint rawColor = *(((TUint16*)slptr) + coordmap.iX);
  1065 						TInt red = (rawColor   & 0xF800)>>8;
  1066 						red += red>>5;
  1067 						TInt green = (rawColor & 0x07E0)>>3;
  1068 						green += green>>6;
  1069 						TInt blue = (rawColor  & 0x001F)<<3;
  1070 						blue += blue>>5;
  1071 						lastColor = 0xff000000 | (red << 16) | (green << 8) | blue;
  1072 						lastcoord = coordmap.iX;
  1073 						}
  1074 					*pixelPtr++ = lastColor;
  1075 					if (stretchmap.SingleStep(coordmap))
  1076 						break;
  1077 					}
  1078 				}
  1079 			else
  1080 				{
  1081 				TRgb lastColor;
  1082 
  1083 				while (pixelPtr < pixelPtrLimit)
  1084 					{
  1085 					if (coordmap.iX > lastcoord)
  1086 						{
  1087 						lastColor = GetRgbPixelEx(coordmap.iX,slptr);
  1088 						lastcoord = coordmap.iX;
  1089 						}
  1090 					*pixelPtr++ = lastColor._Color16MA();//BGRA (Blue/Green/Red) as little endian byte order
  1091 					if (stretchmap.SingleStep(coordmap))
  1092 						break;
  1093 					}
  1094 				}
  1095 			break;
  1096 			}
  1097 		case EColor16MAP:
  1098 			{ //if alpha is not available, assign 255 as alpha (opaque).
  1099 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2);
  1100 			aBuf.SetLength(aClipStrchLen << 2);
  1101 			TInt32* pixelPtr = (TInt32*)bufptr;
  1102 			TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen;
  1103 			if (iHeader.iBitsPerPixel == 32) //32bpp source image => color
  1104 				{
  1105 				TInt lastColor = 0;
  1106 				//pre-multiply if alpha IS available.
  1107 				if(displayMode == EColor16MA)
  1108 					{
  1109 					while (pixelPtr < pixelPtrLimit)
  1110 						{
  1111 						if (coordmap.iX > lastcoord)
  1112 							{
  1113 							lastColor = NonPMA2PMAPixel(*(slptr + coordmap.iX));
  1114 							lastcoord = coordmap.iX;
  1115 							}
  1116 						*pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order
  1117 						if (stretchmap.SingleStep(coordmap))
  1118 							break;
  1119 						}
  1120 					}
  1121 				else if(displayMode == EColor16MU)
  1122 					{
  1123 					while (pixelPtr < pixelPtrLimit)
  1124 						{
  1125 						if (coordmap.iX > lastcoord)
  1126 							{
  1127 							//do not want to convert to non pma, since keep transparency
  1128 							//e.g. alpha 0.5, red 0.5.  Want to keep red as 0.5 since it
  1129 							//is not fully red.  For 16MA convert to 1, and keep 0.5 alpha
  1130 							lastColor = (*(slptr + coordmap.iX))|0xff000000;
  1131 							lastcoord = coordmap.iX;
  1132 							}
  1133 						*pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order
  1134 						if (stretchmap.SingleStep(coordmap))
  1135 							break;
  1136 						}
  1137 					}
  1138 				else	
  1139 					{
  1140 					while (pixelPtr < pixelPtrLimit)
  1141 						{
  1142 						if (coordmap.iX > lastcoord)
  1143 							{
  1144 							lastColor = *(slptr + coordmap.iX);
  1145 							lastcoord = coordmap.iX;
  1146 							}
  1147 						*pixelPtr++ = lastColor;
  1148 						if (stretchmap.SingleStep(coordmap))
  1149 								break;
  1150 						}
  1151 					}
  1152 				}
  1153 				else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color
  1154 					{
  1155 					TInt lastColor = 0;
  1156 					while (pixelPtr < pixelPtrLimit)
  1157 						{
  1158 						if (coordmap.iX > lastcoord)
  1159 							{
  1160 							TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3;
  1161 							lastColor = TUint8(*scanLineBytePointer);
  1162 							scanLineBytePointer++;
  1163 							lastColor |= TUint8(*scanLineBytePointer) << 8;
  1164 							scanLineBytePointer++;
  1165 							lastColor |= TUint8(*scanLineBytePointer) << 16;
  1166 							lastcoord = coordmap.iX;
  1167 							}
  1168 						*pixelPtr++ = (lastColor | 0xff000000);
  1169 						if (stretchmap.SingleStep(coordmap))
  1170 							break;
  1171 						}
  1172 					}
  1173 				else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color
  1174 					{
  1175 					TInt lastColor = 0;
  1176 					while (pixelPtr < pixelPtrLimit)
  1177 						{
  1178 						if (coordmap.iX > lastcoord)
  1179 							{
  1180 							TUint rawColor = *(((TUint16*)slptr) + coordmap.iX);
  1181 							TInt red = (rawColor   & 0xF800)>>8;
  1182 							red += red>>5;
  1183 							TInt green = (rawColor & 0x07E0)>>3;
  1184 							green += green>>6;
  1185 							TInt blue = (rawColor  & 0x001F)<<3;
  1186 							blue += blue>>5;
  1187 							lastColor = 0xff000000 | (red << 16) | (green << 8) | blue;
  1188 							lastcoord = coordmap.iX;
  1189 							}
  1190 						*pixelPtr++ = lastColor;
  1191 						if (stretchmap.SingleStep(coordmap))
  1192 							break;
  1193 						}
  1194 					}
  1195 				else
  1196 					{
  1197 					TRgb lastColor;
  1198 
  1199 					while (pixelPtr < pixelPtrLimit)
  1200 						{
  1201 						if (coordmap.iX > lastcoord)
  1202 							{
  1203 							lastColor = GetRgbPixelEx(coordmap.iX,slptr);
  1204 							lastcoord = coordmap.iX;
  1205 							}
  1206 						*pixelPtr++ = lastColor._Color16MA();//BGRA (Blue/Green/Red) as little endian byte order
  1207 						if (stretchmap.SingleStep(coordmap))
  1208 							break;
  1209 						}
  1210 					}
  1211 				break;
  1212 			}
  1213 		case EGray2:
  1214 			{
  1215 			TBool oddx=(aDitherOffset.iX&1);
  1216 			TBool oddy=(aDitherOffset.iY&1);
  1217 			aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<5));
  1218 			aBuf.SetLength((aClipStrchLen+7)>>3);
  1219 			buflimit+=(aBuf.Length()+3)>>2;
  1220 			while(bufptr<buflimit)
  1221 				{
  1222 				TUint32 mask=1;
  1223 				*bufptr=0;
  1224 				while(mask)
  1225 					{
  1226 					if (coordmap.iX > lastcoord)
  1227 						{
  1228 						lastValue = GetGrayPixelEx(coordmap.iX,slptr);
  1229 						lastcoord = coordmap.iX;
  1230 						}
  1231 					if (HashTo1bpp(lastValue,oddx,oddy))
  1232 						*bufptr|=mask;
  1233 					mask<<=1;
  1234 					oddx^=1;
  1235 					if (stretchmap.SingleStep(coordmap)) break;
  1236 					}
  1237 				bufptr++;
  1238 				}
  1239 			break;
  1240 			}
  1241 		default:
  1242 			Panic(EFbsBitmapInvalidMode);
  1243 		}
  1244 	}
  1245 
  1246 void CBitwiseBitmap::DoCompressScanLine(TDes8& aBuf,TInt x,TInt y,TInt aClipStrchX,TInt aClipStrchLen,TInt aStretchLength,TInt aOrgX,TInt aOrgLen,const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase,TLineScanningPosition& aLineScanningPosition) const
  1247 	{
  1248 	TInt first=0,second=0,third=0,fourth=0,fifth=0,sixth=0,seventh=0,eighth=0;
  1249 	TUint8* bufptr=&aBuf[0];
  1250 	TUint8* buflimit=bufptr;
  1251 	TUint32* slptr=NULL;
  1252 	TPoint pixel(aOrgX,y);
  1253 	TDisplayMode displayMode = iSettings.CurrentDisplayMode();
  1254 	GetScanLinePtr(slptr,aOrgLen,pixel,aBase, aLineScanningPosition);
  1255 	if (!slptr)
  1256 		{
  1257 		WhiteFill((TUint8*)aBuf.Ptr(),aBuf.MaxLength(),displayMode);
  1258 		return;
  1259 		}
  1260 	TLinearDDA stretchmap;
  1261 	TPoint coordmap(aOrgX,0);
  1262 	stretchmap.Construct(coordmap,coordmap+TPoint(aOrgLen,aStretchLength),TLinearDDA::ELeft);
  1263 	coordmap.iY=aClipStrchX;
  1264 	if (aClipStrchX>0) stretchmap.JumpToYCoord(coordmap.iX,coordmap.iY);
  1265 	else stretchmap.NextStep(coordmap);
  1266 	switch(aDispMode)
  1267 		{
  1268 		case EGray4:
  1269 			{
  1270 			aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<2));
  1271 			aBuf.SetLength((aClipStrchLen+3)>>2);
  1272 			TInt index=((aDitherOffset.iY&1)<<1)+((aDitherOffset.iX+x)&1);
  1273 			buflimit+=aBuf.Length();
  1274 			if (displayMode==EGray16)
  1275 				{
  1276 				while(bufptr<buflimit)
  1277 					{
  1278 					first=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
  1279 					index^=1;
  1280 					stretchmap.NextStep(coordmap);
  1281 					second=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
  1282 					index^=1;
  1283 					stretchmap.NextStep(coordmap);
  1284 					third=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
  1285 					index^=1;
  1286 					stretchmap.NextStep(coordmap);
  1287 					fourth=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
  1288 					index^=1;
  1289 					*bufptr++=TUint8(first|(second<<2)|(third<<4)|(fourth<<6));
  1290 					stretchmap.NextStep(coordmap);
  1291 					}
  1292 				}
  1293 			else
  1294 				{
  1295 				while(bufptr<buflimit)
  1296 					{
  1297 					first=GetGrayPixelEx(coordmap.iX,slptr)>>6;
  1298 					stretchmap.NextStep(coordmap);
  1299 					second=GetGrayPixelEx(coordmap.iX,slptr)>>6;
  1300 					stretchmap.NextStep(coordmap);
  1301 					third=GetGrayPixelEx(coordmap.iX,slptr)>>6;
  1302 					stretchmap.NextStep(coordmap);
  1303 					fourth=GetGrayPixelEx(coordmap.iX,slptr)>>6;
  1304 					*bufptr++=TUint8(first|(second<<2)|(third<<4)|(fourth<<6));
  1305 					stretchmap.NextStep(coordmap);
  1306 					}
  1307 				}
  1308 			break;
  1309 			}
  1310 		case EGray16:
  1311 			{
  1312 			aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<1));
  1313 			aBuf.SetLength((aClipStrchLen+1)>>1);
  1314 			buflimit+=aBuf.Length();
  1315 			while(bufptr<buflimit)
  1316 				{
  1317 				first = GetGrayPixelEx(coordmap.iX,slptr) >> 4;
  1318 				stretchmap.NextStep(coordmap);
  1319 				first |= GetGrayPixelEx(coordmap.iX,slptr) & 0xf0;
  1320 				*bufptr++ = TUint8(first);
  1321 				stretchmap.NextStep(coordmap);
  1322 				}
  1323 			break;
  1324 			}
  1325 		case EColor16:
  1326 			{
  1327 			aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<1));
  1328 			aBuf.SetLength((aClipStrchLen+1)>>1);
  1329 			buflimit+=aBuf.Length();
  1330 			while(bufptr<buflimit)
  1331 				{
  1332 				first = GetRgbPixelEx(coordmap.iX,slptr).Color16();
  1333 				stretchmap.NextStep(coordmap);
  1334 				first |= GetRgbPixelEx(coordmap.iX,slptr).Color16() << 4;
  1335 				*bufptr++ = TUint8(first);
  1336 				stretchmap.NextStep(coordmap);
  1337 				}
  1338 			break;
  1339 			}
  1340 		case EGray256:
  1341 			{
  1342 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength());
  1343 			aBuf.SetLength(aClipStrchLen);
  1344 			buflimit += aBuf.Length();
  1345 
  1346 			while(bufptr < buflimit)
  1347 				{
  1348 				*bufptr++ = GetGrayPixelEx(coordmap.iX,slptr);
  1349 				stretchmap.NextStep(coordmap);
  1350 				}
  1351 			break;
  1352 			}
  1353 		case EColor256:
  1354 			{
  1355 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength());
  1356 			aBuf.SetLength(aClipStrchLen);
  1357 			buflimit += aBuf.Length();
  1358 
  1359 			while(bufptr < buflimit)
  1360 				{
  1361 				*bufptr++ = TUint8(GetRgbPixelEx(coordmap.iX,slptr).Color256());
  1362 				stretchmap.NextStep(coordmap);
  1363 				}
  1364 			break;
  1365 			}
  1366 		case EColor4K:
  1367 			{
  1368 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1);
  1369 			aBuf.SetLength(aClipStrchLen << 1);
  1370 			buflimit += aBuf.Length();
  1371 
  1372 			while(bufptr < buflimit)
  1373 				{
  1374 				*((TUint16*)bufptr) = TUint16(GetRgbPixelEx(coordmap.iX,slptr)._Color4K());
  1375 				bufptr += 2;
  1376 				stretchmap.NextStep(coordmap);
  1377 				}
  1378 			break;
  1379 			}
  1380 		case EColor64K:
  1381 			{
  1382 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1);
  1383 			aBuf.SetLength(aClipStrchLen << 1);
  1384 			buflimit += aBuf.Length();
  1385 
  1386 			while(bufptr < buflimit)
  1387 				{
  1388 				*((TUint16*)bufptr) = TUint16(GetRgbPixelEx(coordmap.iX,slptr)._Color64K());
  1389 				bufptr += 2;
  1390 				stretchmap.NextStep(coordmap);
  1391 				}
  1392 			break;
  1393 			}
  1394 		case EColor16M:
  1395 			{
  1396 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / 3);
  1397 			aBuf.SetLength(aClipStrchLen * 3);
  1398 			buflimit += aBuf.Length();
  1399 
  1400 			while(bufptr<buflimit)
  1401 				{
  1402 				TInt color16M = GetRgbPixelEx(coordmap.iX,slptr)._Color16M();
  1403 				*bufptr++ = TUint8(color16M);
  1404 				*bufptr++ = TUint8(color16M >> 8);
  1405 				*bufptr++ = TUint8(color16M >> 16);
  1406 				stretchmap.NextStep(coordmap);
  1407 				}
  1408 			break;
  1409 			}
  1410 		case ERgb:
  1411 		case EColor16MU:
  1412 		case EColor16MA:
  1413 		case EColor16MAP:
  1414 			{
  1415 			aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2);
  1416 			aBuf.SetLength(aClipStrchLen << 2);
  1417 			TUint32* pixelPtr = (TUint32*)bufptr;
  1418 			TUint32* pixelPtrLimit = pixelPtr + aClipStrchLen;
  1419 			if (aDispMode == EColor16MAP && displayMode == EColor16MA)
  1420 			while(pixelPtr < pixelPtrLimit)
  1421 				{
  1422 					*pixelPtr++ = NonPMA2PMAPixel(*(slptr + coordmap.iX));
  1423 				stretchmap.NextStep(coordmap);
  1424 				}
  1425 			else if (aDispMode == EColor16MAP && displayMode == EColor16MAP)
  1426 				while(pixelPtr < pixelPtrLimit)
  1427 					{
  1428 					*pixelPtr++ = *(slptr + coordmap.iX);
  1429 					stretchmap.NextStep(coordmap);
  1430 					}
  1431 			else if (aDispMode == EColor16MU)
  1432 				while(pixelPtr < pixelPtrLimit)
  1433 					{
  1434 					*pixelPtr++ = GetRgbPixelEx(coordmap.iX, slptr).Internal();
  1435 					stretchmap.NextStep(coordmap);
  1436 					}
  1437 			else
  1438 				while(pixelPtr < pixelPtrLimit)
  1439 					{
  1440 					*pixelPtr++ = GetRgbPixelEx(coordmap.iX, slptr).Internal();
  1441 					stretchmap.NextStep(coordmap);
  1442 				}
  1443 			break;
  1444 			}
  1445 		case EGray2:
  1446 			{
  1447 			TBool oddx=(aDitherOffset.iX&1);
  1448 			TBool oddy=(aDitherOffset.iY&1);
  1449 			aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<3));
  1450 			aBuf.SetLength((aClipStrchLen+7)>>3);
  1451 			buflimit+=aBuf.Length();
  1452 			while(bufptr<buflimit)
  1453 				{
  1454 				first=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
  1455 				stretchmap.NextStep(coordmap);
  1456 				second=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
  1457 				stretchmap.NextStep(coordmap);
  1458 				third=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
  1459 				stretchmap.NextStep(coordmap);
  1460 				fourth=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
  1461 				stretchmap.NextStep(coordmap);
  1462 				fifth=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
  1463 				stretchmap.NextStep(coordmap);
  1464 				sixth=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
  1465 				stretchmap.NextStep(coordmap);
  1466 				seventh=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
  1467 				stretchmap.NextStep(coordmap);
  1468 				eighth=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
  1469 				*bufptr++=TUint8(first|(second<<1)|(third<<2)|(fourth<<3)|
  1470 					(fifth<<4)|(sixth<<5)|(seventh<<6)|(eighth<<7));
  1471 				stretchmap.NextStep(coordmap);
  1472 				oddx^=1;
  1473 				}
  1474 			break;
  1475 			}
  1476 		default:
  1477 			Panic(EFbsBitmapInvalidMode);
  1478 		}
  1479 	}