os/graphics/fbs/fontandbitmapserver/sfbs/BITBMP.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1995-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 <fbs.h>
    18 #include <bitmap.h>
    19 #include <graphicsaccelerator.h>
    20 #include <graphics/lookuptable.h>
    21 #include <graphics/blendingalgorithms.h>
    22 #include <graphics/bitmapuid.h>
    23 #include "UTILS.H"
    24 #include <s32mem.h>
    25 #include "ShiftedFileStore.h"
    26 #include "CompileAssert.h"
    27 #include "CompressionBookmark.h"
    28 #include "BitmapCompr.h"
    29 #include "palette.h"
    30 #include "fbsrasterizer.h"
    31 #include "bitmap.inl"
    32 #include "BitwiseBitmap.inl"
    33 #include "bitmapconst.h"
    34 
    35 #ifdef __ARMCC__
    36 #pragma arm
    37 #pragma O3
    38 #pragma Otime
    39 #endif
    40 
    41 const TInt KMaxPixelSize = KMaxTInt / 4; // Maximum pixel size to avoid some overflow problems
    42 const TUint KMaxByteSize = TUint(KMaxTInt / 2); // Maximum byte size to avoid other overflow problems
    43 enum
    44     {
    45     EFirstTime = 65536
    46     };
    47 GLREF_C void Panic(TFbsPanic aPanic);
    48 
    49 #define COLOR_VALUE(ScanLinePtr, XPos) (*((ScanLinePtr) + ((XPos) >> 5)) & ( 1 << ((XPos) & 0x1F)))
    50 
    51 EXPORT_C void CBitwiseBitmap::operator delete(TAny *aThis)
    52 	{
    53 	if (((CBitwiseBitmap*)aThis)->iHeap)
    54 		((CBitwiseBitmap*)aThis)->iHeap->Free(aThis);
    55 	}
    56 
    57 EXPORT_C CBitwiseBitmap::CBitwiseBitmap(RHeap* aHeap,CChunkPile* aPile):
    58 	iUid(KCBitwiseBitmapUid),
    59 	iSettings(ENone),
    60 	iHeap(aHeap),
    61 	iPile(aPile),
    62 	iByteWidth(0),
    63 	iDataOffset(0),
    64 	iIsCompressedInRAM(EFalse)
    65 	{
    66 	//CBitwiseBitmap size can't be changed! If the bitmap is ROM based,
    67 	//then CBitwiseBitmap object is not created, but CBitwiseBitmap pointer is
    68 	//used to access ROM based bitmap data.
    69 	//The following line is a part of CFbsBitmap::DoLoad(...) source code:
    70 	//iRomPointer=(CBitwiseBitmap*)(((TUint8*)rompointer)+offset);
    71 	//We have to preserve data compatibility with already existing ROM bitmaps.
    72 	enum
    73 		{
    74 		KCBitwiseBitmapSize = 72
    75 		};
    76 	COMPILE_TIME_ASSERT(sizeof(CBitwiseBitmap) == KCBitwiseBitmapSize);
    77 #ifdef SYMBIAN_DEBUG_FBS_LOCKHEAP
    78 	Extra()->iLockCount = 0;
    79 	Extra()->iThreadId = TThreadId(KNullThreadId);
    80 #endif
    81 	Extra()->iTouchCount = 0;
    82 	Extra()->iSerialNumber = 0;
    83 	}
    84 
    85 EXPORT_C CBitwiseBitmap::~CBitwiseBitmap()
    86 	{
    87 	Reset();
    88 	}
    89 
    90 EXPORT_C void CBitwiseBitmap::Reset()
    91 	{
    92 	if (iDataOffset)
    93 		{
    94 		if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid)
    95 			{
    96 			RHardwareBitmap hwb(iDataOffset);	// iDataOffset = handle for hardware bitmap
    97 			hwb.Destroy();
    98 			}
    99 		else
   100 			if (iPile) iPile->Free(DataAddress());
   101 		}
   102 	iUid.iUid = KCBitwiseBitmapUid.iUid;
   103 	iDataOffset=0;
   104 	iSettings.SetDisplayModes(ENone);
   105 	iByteWidth=0;
   106 	iHeader=SEpocBitmapHeader();
   107 	iIsCompressedInRAM=EFalse;
   108 	}
   109 
   110 EXPORT_C TUid CBitwiseBitmap::Uid() const
   111 	{
   112 	return(iUid);
   113 	}
   114 
   115 EXPORT_C TInt CBitwiseBitmap::Construct(const TSize& aSize,TDisplayMode aDispMode,TUid aCreatorUid)
   116 	{
   117 	if (iHeap == NULL || iPile == NULL)
   118 		return KErrNoMemory;
   119 
   120 	if (aSize.iWidth > KMaxPixelSize || aSize.iHeight > KMaxPixelSize)
   121 		return KErrTooBig;
   122 
   123 	TUint8* data = NULL;
   124 	Reset();
   125 
   126 	iSettings.SetDisplayModes(aDispMode);
   127 	iByteWidth = ByteWidth(aSize.iWidth,aDispMode);
   128 
   129 	TInt64 hugeDataSize = TInt64(aSize.iHeight) * TInt64(iByteWidth);
   130 	if (I64HIGH(hugeDataSize) != 0 || I64LOW(hugeDataSize) > KMaxByteSize)
   131 		return KErrTooBig;
   132 
   133 	TInt dataSize = I64LOW(hugeDataSize);
   134 	iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + dataSize;
   135 	iHeader.iStructSize = sizeof(SEpocBitmapHeader);
   136 	iHeader.iSizeInPixels = aSize;
   137 	iHeader.iSizeInTwips = TSize(0,0);
   138 	iHeader.iBitsPerPixel = Bpp(aDispMode);
   139 	iHeader.iColor = IsColor(aDispMode);
   140 	iHeader.iPaletteEntries = 0;
   141 	iHeader.iCompression = ENoBitmapCompression;
   142 
   143 	if (aSize.iHeight && aSize.iWidth)
   144 		{
   145 		if(aCreatorUid!=KUidCFbsBitmapCreation)
   146 			{
   147 			RHardwareBitmap hwb;
   148 			TAcceleratedBitmapInfo info;
   149 			TInt ret = hwb.Create(aDispMode,aSize,aCreatorUid);
   150 			if(ret==KErrNone)
   151 				ret = hwb.GetInfo(info);
   152 			if(ret!=KErrNone)
   153 				{
   154 				Reset();
   155 				return ret;
   156 				}
   157 
   158 			iSettings.SetVolatileBitmap();
   159 			data = info.iAddress;
   160 			dataSize = info.iLinePitch*info.iSize.iHeight;
   161 			__ASSERT_DEBUG(info.iLinePitch >= iByteWidth, ::Panic(EFbsHardwareBitmapError));
   162 			iByteWidth = info.iLinePitch;
   163 
   164 			iDataOffset = hwb.iHandle;	// iDataOffset = handle for hardware bitmap
   165 			iUid.iUid = KCBitwiseBitmapHardwareUid.iUid;
   166 #ifdef SYMBIAN_DISABLE_HARDWARE_BITMAP_WHITEFILL
   167 			return KErrNone;
   168 #endif
   169 			}
   170 		else
   171 			{
   172 			data = iPile->Alloc(dataSize);
   173 			iDataOffset = data - iPile->ChunkBase();
   174 			}
   175 		if (!data)
   176 			{
   177 			iDataOffset=0;
   178 			Reset();
   179 			return(KErrNoMemory);	// no memory exit point
   180 			}
   181 		}
   182 
   183 	if (dataSize < KMaxLargeBitmapAlloc || aDispMode == EColor4K || iUid.iUid == KCBitwiseBitmapHardwareUid.iUid)
   184 		{
   185 		WhiteFill(data,dataSize,aDispMode);
   186 		}
   187 
   188 	return KErrNone;	// success exit point
   189 	}
   190 
   191 
   192 EXPORT_C TInt CBitwiseBitmap::ConstructExtended(const TSize& aSize, TDisplayMode aDispMode, TUid aType, TInt aDataSize)
   193 	{
   194 	if (iHeap == NULL || iPile == NULL)
   195 		return KErrNoMemory;
   196 	if (aSize.iWidth > KMaxPixelSize || aSize.iHeight > KMaxPixelSize)
   197 		return KErrTooBig;
   198 	if (aType.iUid == KCBitwiseBitmapUid.iUid || aType.iUid == KCBitwiseBitmapHardwareUid.iUid)
   199 		return KErrArgument; // make sure the extended bitmap type is not one of the standard types
   200 	if (aDataSize > KMaxByteSize)
   201 		return KErrTooBig;
   202 	Reset();
   203 	iUid = aType;
   204 	iSettings.SetDisplayModes(aDispMode);
   205 	iByteWidth = ByteWidth(aSize.iWidth, aDispMode);
   206 	iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + aDataSize;
   207 	iHeader.iStructSize = sizeof(SEpocBitmapHeader);
   208 	iHeader.iSizeInPixels = aSize;
   209 	iHeader.iSizeInTwips = TSize(0,0);
   210 	iHeader.iBitsPerPixel = Bpp(aDispMode);
   211 	iHeader.iColor = IsColor(aDispMode);
   212 	iHeader.iPaletteEntries = 0;
   213 	iHeader.iCompression = EProprietaryCompression;
   214 	TUint8* data = iPile->Alloc(aDataSize);
   215 	if (!data)
   216 		{
   217 		Reset();
   218 		return KErrNoMemory;
   219 		}
   220 	iDataOffset = data - iPile->ChunkBase();
   221 	return KErrNone;
   222 	}
   223 
   224 
   225 EXPORT_C void CBitwiseBitmap::ConstructL(RFs& aFs,const TDesC& aFilename,TInt32 aId,TUint aFileOffset)
   226 	{
   227 	//If aFileOffset != 0 then aFilename is a file with an embedded MBM file section at the end.
   228 	//The implementation uses the fact that mbm files are implemented as
   229 	//filestores and stream ID is actually the offset from the beginning of the filestore.
   230 	//If stream ID changes its meaning in the future -
   231 	//the method implementation has to be reviewed and changed too.
   232 	User::LeaveIfNull(iHeap);
   233 	User::LeaveIfNull(iPile);
   234 	TUint fileMode = EFileRead;
   235 	if(aFileOffset != 0) //This is a file with an embedded MBM file section at the end.
   236 		fileMode |= EFileShareReadersOnly;
   237 	CShiftedFileStore* filestore = CShiftedFileStore::OpenLC(aFs,aFilename,fileMode,aFileOffset);
   238 	TStreamId streamid = filestore->Root();
   239 	//TStreamId is the offset from the beggining of the file.
   240 	//Obviously, if the bitmap file section is at the middle of the physical file,
   241 	//we should add aFileOffset value to TStreamId value and use it.
   242 	TStreamId streamid2(streamid.Value() + aFileOffset);
   243 	RStoreReadStream readstream;
   244 	readstream.OpenLC(*filestore,streamid2);
   245 	TInt numbitmaps = readstream.ReadInt32L();
   246 	if (aId < 0 || aId >= numbitmaps)
   247 		User::Leave(KErrEof);
   248 
   249 	TStreamId bmpstreamid;
   250 	bmpstreamid.InternalizeL(readstream);
   251 	TStreamId bmpstreamid2(bmpstreamid.Value() + aFileOffset);
   252 	for (TInt count = 0; count < aId; count++)
   253 		{
   254 		bmpstreamid2.InternalizeL(readstream);
   255 		bmpstreamid2 = TStreamId(bmpstreamid2.Value() + aFileOffset);
   256 		}
   257 
   258 	CleanupStack::PopAndDestroy();
   259 	RStoreReadStream bmpstream;
   260 	bmpstream.OpenLC(*filestore,bmpstreamid2);
   261 	InternalizeL(bmpstream);
   262 	CleanupStack::PopAndDestroy(2);
   263 	}
   264 
   265 EXPORT_C void CBitwiseBitmap::ConstructL(RFile& aFile,TInt32 aId,TUint aFileOffset)
   266 	{
   267 	//If aFileOffset != 0 then aFilename is a file with an embedded MBM file section at the end.
   268 	//The implementation uses the fact that mbm files are implemented as
   269 	//filestores and stream ID is actually the offset from the beginning of the filestore.
   270 	//If stream ID changes its meaning in the future -
   271 	//the method implementation has to be reviewed and changed too.
   272 	User::LeaveIfNull(iHeap);
   273 	User::LeaveIfNull(iPile);
   274 
   275 	CShiftedFileStore* filestore = CShiftedFileStore::FromL(aFile,aFileOffset);
   276 	CleanupStack::PushL(filestore);
   277 	TStreamId streamid = filestore->Root();
   278 	//TStreamId is the offset from the beggining of the file.
   279 	//Obviously, if the bitmap file section is at the middle of the physical file,
   280 	//we should add aFileOffset value to TStreamId value and use it.
   281 	TStreamId streamid2(streamid.Value() + aFileOffset);
   282 	RStoreReadStream readstream;
   283 	readstream.OpenLC(*filestore,streamid2);
   284 	TInt numbitmaps = readstream.ReadInt32L();
   285 	if (aId < 0 || aId >= numbitmaps)
   286 		User::Leave(KErrEof);
   287 	//Retrieving the streamid of the bitmap of that id from the file
   288 	TStreamId bmpstreamid;
   289 	bmpstreamid.InternalizeL(readstream);
   290 	TStreamId bmpstreamid2(bmpstreamid.Value() + aFileOffset);
   291 	for (TInt count = 0; count < aId; count++)
   292 		{
   293 		bmpstreamid2.InternalizeL(readstream);
   294 		bmpstreamid2 = TStreamId(bmpstreamid2.Value() + aFileOffset);
   295 		}
   296 	//Use the streamid found to initialize the bitmap raw data in the memory
   297 	CleanupStack::PopAndDestroy(&readstream);
   298 	RStoreReadStream bmpstream;
   299 	bmpstream.OpenLC(*filestore,bmpstreamid2);
   300 	InternalizeL(bmpstream);
   301 	CleanupStack::PopAndDestroy(2,filestore);
   302 	}
   303 
   304 
   305 EXPORT_C void CBitwiseBitmap::ConstructL(CShiftedFileStore* aFileStore,TStreamId aStreamId)
   306 	{
   307 	User::LeaveIfNull(iHeap);
   308 	User::LeaveIfNull(iPile);
   309 
   310 	RStoreReadStream bmpstream;
   311 	bmpstream.OpenLC(*aFileStore,aStreamId);
   312 	InternalizeL(bmpstream);
   313 	CleanupStack::PopAndDestroy();
   314 	}
   315 
   316 EXPORT_C TInt CBitwiseBitmap::CopyData(const CBitwiseBitmap& aSourceBitmap)
   317 	{
   318 	__ASSERT_DEBUG(iHeap && iPile, ::Panic(EFbsPanicBitmapDataCopy));
   319 	__ASSERT_DEBUG(!iIsCompressedInRAM, ::Panic(EFbsPanicBitmapDataCopy));
   320 	__ASSERT_DEBUG(iUid.iUid == KCBitwiseBitmapUid.iUid, ::Panic(EFbsPanicBitmapDataCopy));
   321 	if (aSourceBitmap.iUid.iUid != KCBitwiseBitmapUid.iUid)
   322 		return KErrNotSupported;
   323 	const TDisplayMode displayMode = aSourceBitmap.iSettings.CurrentDisplayMode();
   324 	__ASSERT_DEBUG(iSettings.CurrentDisplayMode() == displayMode, ::Panic(EFbsPanicBitmapDataCopy));
   325 	if (aSourceBitmap.iHeader.iSizeInPixels.iWidth > 0)
   326 		iHeader.iSizeInTwips.iWidth = (aSourceBitmap.iHeader.iSizeInTwips.iWidth * iHeader.iSizeInPixels.iWidth)
   327 			/ aSourceBitmap.iHeader.iSizeInPixels.iWidth;
   328 	if (aSourceBitmap.iHeader.iSizeInPixels.iHeight > 0)
   329 		iHeader.iSizeInTwips.iHeight = (aSourceBitmap.iHeader.iSizeInTwips.iHeight * iHeader.iSizeInPixels.iHeight)
   330 			/ aSourceBitmap.iHeader.iSizeInPixels.iHeight;
   331 	TUint32* destBase = DataAddress();
   332 	TUint32* srcBase = aSourceBitmap.DataAddress();
   333 	if (!destBase || !srcBase)
   334 		return KErrNone;
   335 	TInt minPixelHeight = Min(iHeader.iSizeInPixels.iHeight, aSourceBitmap.iHeader.iSizeInPixels.iHeight);
   336 	if (aSourceBitmap.iIsCompressedInRAM)
   337 		{
   338 		TUint8* dest = (TUint8*)destBase;
   339 		TInt minPixelWidth = Min(iHeader.iSizeInPixels.iWidth, aSourceBitmap.iHeader.iSizeInPixels.iWidth);
   340 		TPtr8 pDest(dest, iByteWidth, iByteWidth);
   341 		TPoint pt(0, 0);
   342 		TPoint ditherOffset(0, 0);
   343 		TLineScanningPosition scanPos(srcBase);
   344 		scanPos.iScanLineBuffer = HBufC8::New(aSourceBitmap.iByteWidth + 4);
   345 		if (!scanPos.iScanLineBuffer)
   346 			return KErrNoMemory;
   347 		for (TInt row = 0; row < minPixelHeight; ++row)
   348 			{
   349 			pDest.Set(dest, iByteWidth, iByteWidth);
   350 			pt.iY = row;
   351 			aSourceBitmap.GetScanLine(pDest, pt, minPixelWidth, EFalse, ditherOffset, displayMode, srcBase, scanPos);
   352 			dest += iByteWidth;
   353 			}
   354 		delete scanPos.iScanLineBuffer;
   355 		}
   356 	else
   357 		{
   358 		TUint8* dest = (TUint8*)destBase;
   359 		TUint8* src = (TUint8*)srcBase;
   360 		TInt minByteWidth = Min(iByteWidth, aSourceBitmap.iByteWidth);
   361 		for(TInt row = 0; row < minPixelHeight; ++row)
   362 			{
   363 			Mem::Copy(dest, src, minByteWidth);
   364 			dest += iByteWidth;
   365 			src += aSourceBitmap.iByteWidth;
   366 			}
   367 		}
   368 	if (iHeader.iSizeInPixels.iWidth > aSourceBitmap.iHeader.iSizeInPixels.iWidth)
   369 		{
   370 		TInt extraBits = (aSourceBitmap.iHeader.iSizeInPixels.iWidth * aSourceBitmap.iHeader.iBitsPerPixel) & 31;
   371 		if (extraBits > 0)
   372 			{
   373 			TUint32 mask = KMaxTUint32;
   374 			mask <<= extraBits;
   375 			TInt destWordWidth = iByteWidth >> 2;
   376 			TInt srcWordWidth = aSourceBitmap.iByteWidth >> 2;
   377 			TUint32* maskAddress = destBase + srcWordWidth - 1;
   378 			for (TInt row = 0; row < minPixelHeight; ++row)
   379 				{
   380 				*maskAddress |= mask;
   381 				maskAddress += destWordWidth;
   382 				}
   383 			}
   384 		}
   385 	return KErrNone;
   386 	}
   387 
   388 EXPORT_C void CBitwiseBitmap::ExternalizeL(RWriteStream& aStream,const CFbsBitmap& aHandleBitmap) const
   389 	{
   390 	ExternalizeRectangleL(aStream,iHeader.iSizeInPixels,aHandleBitmap);
   391 	}
   392 
   393 EXPORT_C void CBitwiseBitmap::ExternalizeRectangleL(RWriteStream& aStream,const TRect& aRect,const CFbsBitmap& aHandleBitmap) const
   394 	{
   395 	if (aRect.IsEmpty())
   396 		User::Leave(KErrArgument);
   397 	// the bitmap must have been already prepared for data access
   398 	if (aHandleBitmap.iUseCount == 0)
   399 		User::Leave(KErrArgument);
   400 
   401 	// If the bitmap is palette-compressed in RAM externalisation is currently not supported
   402 	// Externalisation of extended bitmaps is currently not supported either
   403 	if (iHeader.iCompression == EGenericPaletteCompression || iHeader.iCompression == EProprietaryCompression)
   404 		User::Leave(KErrNotSupported);
   405 	const TRect bitmapRect(iHeader.iSizeInPixels);
   406 	TRect sourceRect(aRect);
   407 	if (!sourceRect.Intersects(bitmapRect))
   408 		User::Leave(KErrTooBig);
   409 	sourceRect.Intersection(bitmapRect);
   410 
   411 	TDisplayMode displayMode = iSettings.CurrentDisplayMode();
   412 	const TInt scanLineByteLength = CBitwiseBitmap::ByteWidth(sourceRect.Width(),displayMode);
   413 	const TInt rectByteSize = sourceRect.Height() * scanLineByteLength;
   414 	TUint8* buffer = (TUint8*)User::AllocLC(scanLineByteLength);
   415 
   416 	TPtr8 scanline(buffer,scanLineByteLength,scanLineByteLength);
   417 	scanline.Fill(0xff);
   418 	const TPoint zeroPoint;
   419 	TInt compressedSize = 0;
   420 	TInt row;
   421 
   422 	for (row = sourceRect.iTl.iY; row < sourceRect.iBr.iY; row++)
   423 		{
   424 		GetScanLine(scanline,TPoint(sourceRect.iTl.iX,row),sourceRect.Width(),EFalse,zeroPoint,displayMode,aHandleBitmap.DataAddress());
   425 		compressedSize += SizeOfDataCompressed(buffer,scanLineByteLength);
   426 		}
   427 
   428 	TBool compress = EFalse;
   429 	if(compressedSize > 0)
   430 		{
   431 		compress = (displayMode == EColor4K) || (compressedSize < (rectByteSize >> 1) + (rectByteSize >> 2));
   432 		}
   433 
   434 	aStream.WriteInt32L(sizeof(SEpocBitmapHeader) + ((compress) ? compressedSize : rectByteSize));
   435 	aStream.WriteInt32L(iHeader.iStructSize);
   436 	aStream.WriteInt32L(sourceRect.Width());
   437 	aStream.WriteInt32L(sourceRect.Height());
   438 	aStream.WriteInt32L(HorizontalPixelsToTwips(sourceRect.Width()));
   439 	aStream.WriteInt32L(VerticalPixelsToTwips(sourceRect.Height()));
   440 	aStream.WriteInt32L(iHeader.iBitsPerPixel);
   441 	aStream.WriteUint32L(iHeader.iColor);
   442 	aStream.WriteInt32L(0);
   443 	aStream.WriteUint32L(compress ? CompressionType(iHeader.iBitsPerPixel, iHeader.iColor) : ENoBitmapCompression);
   444 
   445 	for (row = sourceRect.iTl.iY; row < sourceRect.iBr.iY; row++)
   446 		{
   447 		GetScanLine(scanline,TPoint(sourceRect.iTl.iX,row),sourceRect.Width(),EFalse,zeroPoint,displayMode,aHandleBitmap.DataAddress());
   448 
   449 		if (!compress)
   450 			aStream.WriteL(buffer,scanLineByteLength);
   451 		else
   452 			DoExternalizeDataCompressedL(aStream,buffer,scanLineByteLength);
   453 		}
   454 
   455 	CleanupStack::PopAndDestroy(); // buffer
   456 	}
   457 
   458 EXPORT_C void CBitwiseBitmap::InternalizeHeaderL(RReadStream& aStream,SEpocBitmapHeader& aHeader)
   459 	{
   460 	aHeader.iBitmapSize=aStream.ReadInt32L();
   461 	aHeader.iStructSize=aStream.ReadInt32L();
   462 	if (aHeader.iStructSize!=sizeof(SEpocBitmapHeader)) User::Leave(KErrCorrupt);
   463 	aHeader.iSizeInPixels.iWidth=aStream.ReadInt32L();
   464 	aHeader.iSizeInPixels.iHeight=aStream.ReadInt32L();
   465 	aHeader.iSizeInTwips.iWidth=aStream.ReadInt32L();
   466 	aHeader.iSizeInTwips.iHeight=aStream.ReadInt32L();
   467 	aHeader.iBitsPerPixel=aStream.ReadInt32L();
   468 	aHeader.iColor=(TInt)aStream.ReadUint32L();
   469 	aHeader.iPaletteEntries=aStream.ReadInt32L();
   470 	if (aHeader.iPaletteEntries != 0)
   471 		{
   472 		//Palettes are not supported.
   473 		User::Leave(KErrNotSupported);
   474 		}
   475 	aHeader.iCompression=(TBitmapfileCompression)aStream.ReadUint32L();
   476 	CheckHeaderIsValidL(aHeader);
   477 	}
   478 
   479 void CBitwiseBitmap::CheckHeaderIsValidL(const SEpocBitmapHeader& aHeader)	
   480 	{
   481 	//These fields are signed in the structure?
   482 	TInt bitmapSize = aHeader.iBitmapSize;
   483 	TInt imageHeightPix = aHeader.iSizeInPixels.iHeight;
   484 	TInt imageWidthPix = aHeader.iSizeInPixels.iWidth;
   485 	TInt bitsPerPixel = aHeader.iBitsPerPixel;
   486 	TInt compression = aHeader.iCompression;
   487 	TInt colour = aHeader.iColor;
   488 	TBool corruptFlag = EFalse;
   489 	
   490 	//Need to copy the values from the structure
   491 	TDisplayMode equivalentMode = CBitwiseBitmap::DisplayMode(aHeader.iBitsPerPixel,aHeader.iColor);
   492 	if (equivalentMode == ENone)
   493 		{
   494 		User::Leave(KErrNotSupported);	
   495 		}
   496 	if(aHeader.iColor < 0)
   497 		 {
   498 		 corruptFlag = ETrue;
   499 		 } 
   500 	 	//easieast way to check if compression type is appropriate is to ask the compressor 
   501 	if (compression && compression!= CBitwiseBitmap::CompressionType(bitsPerPixel,colour))
   502 		{
   503 		corruptFlag = ETrue;
   504 		}
   505 	//danger when using CBitwiseBitmap is they could panic for bad input...
   506 	if (imageHeightPix <= 0 || imageWidthPix <= 0 || bitsPerPixel <= 0)
   507 		{
   508 		corruptFlag = ETrue;
   509 		}
   510 	const TInt KMeg = 1024 * 1024;
   511 	//Test that scanline bytes calculation won't overflow.
   512 	TInt bytesPerPack;	// pixel size in memory
   513 	TInt bytesPerCompression;	// compressed unit data size
   514     User::LeaveIfError(CompressedFormatInfo(equivalentMode, bytesPerPack, bytesPerCompression));
   515 	if (imageWidthPix > 2047 * KMeg / bytesPerPack)
   516 		{
   517 		corruptFlag = ETrue;
   518 		}
   519 	TInt uncompressedWidthBytes = CBitwiseBitmap::ByteWidth(imageWidthPix,equivalentMode);	//we know this won't overflow, now.
   520 	//use top set bit indexes of 32 bit integer values to estimate when W*H multiply will overflow
   521 	TInt exponentWidth = 0;
   522 	TInt exponentHeight = 0;
   523 	if (uncompressedWidthBytes & 0xffff0000)
   524 		{
   525 		exponentWidth += 16;
   526 		}
   527 	if (imageHeightPix & 0xffff0000)
   528 		{
   529 		exponentHeight += 16;
   530 		}
   531 	if (exponentWidth || exponentHeight)
   532 		{
   533 		if (uncompressedWidthBytes & 0xFF00FF00)
   534 			{
   535 			exponentWidth += 8;
   536 			}
   537 		if (imageHeightPix & 0xFF00FF00)
   538 			{
   539 			exponentHeight += 8;
   540 			}
   541 		if (uncompressedWidthBytes & 0xf0f0f0f0)
   542 			{
   543 			exponentWidth += 4;
   544 			}
   545 		if (imageHeightPix & 0xf0f0f0f0)
   546 			{
   547 			exponentHeight += 4;
   548 			}
   549 		if (uncompressedWidthBytes & 0xCCCCCCCC)
   550 			{
   551 			exponentWidth += 2;
   552 			}
   553 		if (imageHeightPix & 0xCCCCCCCC)
   554 			{
   555 				exponentHeight += 2;
   556 		}
   557 		if (uncompressedWidthBytes & 0xaaaaaaaa)
   558 			{
   559 			exponentWidth += 1;
   560 			}
   561 		if (imageHeightPix & 0xaaaaaaaa)
   562 			{
   563 			exponentHeight += 1;
   564 			}
   565 		TInt exponentTotal = exponentWidth + exponentHeight;
   566 		if (exponentTotal >= 31)
   567 			{
   568 			//The result would defuinitely exceed a signed int
   569 			corruptFlag = ETrue;
   570 			}
   571 		else if (exponentTotal == 30)
   572 			{
   573 			//as a bit test, both "next most significat bits" must be set to cause a carry-over,
   574 			//but that isn't so trivial to test.
   575 			if ((uncompressedWidthBytes >> 1) * imageHeightPix > 1024 * KMeg)
   576 				{
   577 				corruptFlag = ETrue;
   578 				}
   579 			}
   580 		}
   581 	if (compression)
   582 		{
   583 		/* estimate compressed file size limits
   584 		byte compression uses lead code 0..127 = repeat next byte n+1 times. -1..-128 = copy next -n bytes
   585 		16, 24, 32 use byte lead codes as above followed by words, triplets, or dwords
   586 		1,2,4,8,16 all encode any dword alignment buffer padding data as full data values.
   587 		32 doesn't have padding issue. 24 does not encode padding bytes.
   588 		12 bit compression uses 0..15 spare nibble to encode short runs. 0=unique. Can never make file bigger.*/
   589 		if (bitsPerPixel == 12)
   590 			{
   591 			//min file size is 1/16 of rect size
   592 			if (bitmapSize < sizeof(SEpocBitmapHeader) + ((uncompressedWidthBytes * imageHeightPix) / 16))
   593 				{
   594 				corruptFlag = ETrue;	
   595 				}
   596 			if (bitmapSize > sizeof(SEpocBitmapHeader) + uncompressedWidthBytes * imageHeightPix)
   597 				{
   598 				corruptFlag = ETrue;
   599 				}
   600 			}
   601 		else
   602 			{
   603 				TInt packedValsPerFile = (uncompressedWidthBytes / bytesPerPack) * imageHeightPix;
   604 				//for some of the compressors 0 means a run of 2, so max 127 means a run of 129
   605 				TInt estMinCompressedBlocksPerFile = (packedValsPerFile - 1) / 129 + 1;	
   606 				/* Absolute minimum is blocks of 128 repeats possibly spanning multiple scanlines
   607 				This can't be compressed by the current per-scanline compressor,
   608 				but is acceptable to the decompressor. */
   609 				if (bitmapSize < sizeof(SEpocBitmapHeader) + estMinCompressedBlocksPerFile * (bytesPerCompression + 1))
   610 					{
   611 					corruptFlag = ETrue;
   612 					}
   613 			/* Absolute maximum is to store every pixel as a seperate run of 1 byte.
   614 			The current compressor would never do this... but the file is legal! */
   615 				if (bitmapSize > sizeof(SEpocBitmapHeader) + packedValsPerFile * (bytesPerCompression + 1))
   616 					{
   617 					corruptFlag = ETrue;
   618 					}
   619 			}
   620 		}
   621 	else
   622 		{
   623 		if (bitmapSize != sizeof(SEpocBitmapHeader) + uncompressedWidthBytes * imageHeightPix)
   624 			{
   625 			corruptFlag = ETrue;
   626 			}
   627 		}
   628 	if(corruptFlag)
   629 		{
   630 		User::Leave(KErrCorrupt);
   631 		}
   632 			
   633 	}
   634 
   635 /**
   636 Internalizes the bit map contents from a stream.
   637 @param aStream The read stream containing the bit map.
   638 */
   639 EXPORT_C void CBitwiseBitmap::InternalizeL(RReadStream& aStream)
   640 	{
   641 	if (iHeap==NULL || iPile==NULL)
   642 		User::Leave(KErrNoMemory);
   643 	Reset();
   644 	InternalizeHeaderL(aStream,iHeader);
   645 
   646 	TDisplayMode displayMode = DisplayMode(iHeader.iBitsPerPixel,iHeader.iColor);
   647 	if(displayMode == ENone)
   648 		{
   649 		Reset();
   650 		User::Leave(KErrCorrupt);
   651 		}
   652 
   653 	iSettings.SetDisplayModes(displayMode);
   654 
   655 	iByteWidth = ByteWidth(iHeader.iSizeInPixels.iWidth,iSettings.CurrentDisplayMode());
   656 
   657 	TUint8* data=NULL;
   658 	TInt bytesize = iByteWidth * iHeader.iSizeInPixels.iHeight;
   659 	if (bytesize > 0)
   660 		{
   661 		data = iPile->Alloc(bytesize);
   662 		iDataOffset = data - iPile->ChunkBase();
   663 		if (!data)
   664 			{
   665 			iDataOffset=0;
   666 			Reset();
   667 			User::LeaveNoMemory();
   668 			}
   669 		}
   670 	TRAPD(err,DoInternalizeL(aStream,iHeader.iBitmapSize-iHeader.iStructSize,DataAddress()));
   671 	if (err!=KErrNone)
   672 		{
   673 		Reset();
   674 		User::Leave(err);
   675 		}
   676 	}
   677 
   678 
   679 void CBitwiseBitmap::DoInternalizeL(RReadStream& aStream,TInt aSrceSize,TUint32* aBase)
   680 	{
   681 	if (iHeader.iCompression==ENoBitmapCompression)
   682 		aStream.ReadL((TUint8*)aBase,aSrceSize);
   683 	else if (iHeader.iCompression < ERLECompressionLast)
   684 		{
   685 		TBitmapfileCompression compression = iHeader.iCompression;
   686 		iHeader.iCompression = ENoBitmapCompression;
   687 		iHeader.iBitmapSize = iByteWidth*iHeader.iSizeInPixels.iHeight+sizeof(SEpocBitmapHeader);
   688 		DoInternalizeCompressedDataL(aStream,aSrceSize,aBase,compression);
   689 		}
   690  	else
   691 		CheckHeaderIsValidL(iHeader);
   692 	}
   693 
   694 EXPORT_C TDisplayMode CBitwiseBitmap::DisplayMode() const
   695 	{
   696 	return iSettings.CurrentDisplayMode();
   697 	}
   698 
   699 EXPORT_C TInt CBitwiseBitmap::HorizontalPixelsToTwips(TInt aPixels) const
   700 	{
   701 	if (iHeader.iSizeInPixels.iWidth==0)
   702 		return(0);
   703 	TInt twips;
   704 	twips = (aPixels*iHeader.iSizeInTwips.iWidth+(iHeader.iSizeInPixels.iWidth/2))/iHeader.iSizeInPixels.iWidth;
   705 	return(twips);
   706 	}
   707 
   708 EXPORT_C TInt CBitwiseBitmap::VerticalPixelsToTwips(TInt aPixels) const
   709 	{
   710 	if (iHeader.iSizeInPixels.iHeight==0)
   711 		return(0);
   712 	TInt twips;
   713 	twips = (aPixels*iHeader.iSizeInTwips.iHeight+(iHeader.iSizeInPixels.iHeight/2))/iHeader.iSizeInPixels.iHeight;
   714 	return (twips);
   715 	}
   716 
   717 EXPORT_C TSize CBitwiseBitmap::SizeInPixels() const
   718 	{
   719 	return(iHeader.iSizeInPixels);
   720 	}
   721 
   722 EXPORT_C TSize CBitwiseBitmap::SizeInTwips() const
   723 	{
   724 	return(iHeader.iSizeInTwips);
   725 	}
   726 
   727 EXPORT_C TInt CBitwiseBitmap::HorizontalTwipsToPixels(TInt aTwips) const
   728 	{
   729 	if (iHeader.iSizeInTwips.iWidth==0)
   730 		return(0);
   731 	TInt pixels;
   732 	pixels = (aTwips*iHeader.iSizeInPixels.iWidth+(iHeader.iSizeInTwips.iWidth/2))/iHeader.iSizeInTwips.iWidth;
   733 	return(pixels);
   734 	}
   735 
   736 EXPORT_C TInt CBitwiseBitmap::VerticalTwipsToPixels(TInt aTwips) const
   737 	{
   738 	if (iHeader.iSizeInTwips.iHeight==0)
   739 		return(0);
   740 	TInt pixels;
   741 	pixels = (aTwips*iHeader.iSizeInPixels.iHeight+(iHeader.iSizeInTwips.iHeight/2))/iHeader.iSizeInTwips.iHeight;
   742 	return(pixels);
   743 	}
   744 
   745 /**
   746 The method retrieves the red, green, blue (RGB) color value of the pixel with
   747 specified coordinates.
   748 Note: The method works for uncompressed bitmaps and extended bitmaps only.
   749 @internalComponent
   750 @released
   751 @pre aBase != NULL;
   752 @param aColor It will be initialized with the pixel color value on success, otherwise
   753 aColor value will be left unchanged.
   754 @param aPixel Pixel coordinates.
   755 @param aBase It points to the beginning of the bitmap data.
   756 */
   757 EXPORT_C void CBitwiseBitmap::GetPixel(TRgb& aColor,const TPoint& aPixel,TUint32* aBase, CFbsRasterizer* aRasterizer) const
   758 	{
   759 	// This operation is not currently supported for compressed bitmaps.
   760 	if (iHeader.iCompression != ENoBitmapCompression && iHeader.iCompression != EProprietaryCompression)
   761 		{
   762 		__ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
   763 		return;
   764 		}
   765 	if (!iDataOffset)
   766 		return;
   767 
   768 	TInt x=aPixel.iX,y=aPixel.iY;
   769 	if (x < -iHeader.iSizeInPixels.iWidth)
   770 		x %= iHeader.iSizeInPixels.iWidth;
   771 	if (y < -iHeader.iSizeInPixels.iHeight)
   772 		y %= iHeader.iSizeInPixels.iHeight;
   773 	if (x < 0)
   774 		x += iHeader.iSizeInPixels.iWidth;
   775 	if (y < 0)
   776 		y += iHeader.iSizeInPixels.iHeight;
   777 
   778 	if (iHeader.iCompression == EProprietaryCompression)
   779 		{
   780 		if (aRasterizer)
   781 			{
   782 			TUint32* slptr = const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(x,y), 1));
   783 			if (slptr)
   784 				{
   785 				aColor = GetRgbPixelEx(x, slptr);
   786 				}
   787 			else
   788 				{
   789 				// wrong rasterizer for this extended bitmap - return white pixel
   790 				aColor = KRgbWhite;
   791 				}
   792 			}
   793 		else
   794 			{
   795 			// no rasterizer - return white pixel
   796 			aColor = KRgbWhite;
   797 			}
   798 		}
   799 	else
   800 		{
   801 		aColor = GetRgbPixelEx(x,ScanLineAddress(aBase,y));
   802 		}
   803 	}
   804 
   805 EXPORT_C TInt CBitwiseBitmap::GetScanLinePtr(TUint32*& aSlptr, TInt& aLength,TPoint& aPixel,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
   806 	{
   807 	if (!iDataOffset)
   808 		return KErrNone;
   809 	if (aPixel.iX >= iHeader.iSizeInPixels.iWidth || aPixel.iX < -iHeader.iSizeInPixels.iWidth)
   810 		aPixel.iX %= iHeader.iSizeInPixels.iWidth;
   811 	if (aPixel.iY >= iHeader.iSizeInPixels.iHeight || aPixel.iY < -iHeader.iSizeInPixels.iHeight)
   812 		aPixel.iY %= iHeader.iSizeInPixels.iHeight;
   813 	if (aPixel.iX < 0)
   814 		aPixel.iX += iHeader.iSizeInPixels.iWidth;
   815 	if (aPixel.iY < 0)
   816 		aPixel.iY += iHeader.iSizeInPixels.iHeight;
   817 	if (aPixel.iX + aLength > iHeader.iSizeInPixels.iWidth)
   818 		aLength = iHeader.iSizeInPixels.iWidth - aPixel.iX;
   819 	if (iHeader.iCompression != ENoBitmapCompression)
   820 		{
   821 		return DoGetScanLinePtr(aSlptr, aPixel,aLength,aBase,aLineScanningPosition);
   822 		}
   823 	else
   824 		{
   825 		aSlptr = ScanLineAddress(aBase,aPixel.iY);
   826 		}
   827 	return KErrNone;
   828 	}
   829 
   830 EXPORT_C TInt CBitwiseBitmap::GetScanLinePtr(TUint32*& aSlptr, TPoint& aPixel,TInt aLength,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
   831 	{
   832 	return GetScanLinePtr(aSlptr, aLength,aPixel,aBase, aLineScanningPosition);
   833 	}
   834 
   835 TUint8 CBitwiseBitmap::GetGrayPixelEx(TInt aX,TUint32* aScanlinePtr) const
   836 	{
   837 	// returns pixel as EGray256 value (0 - 255)
   838 
   839 	if (iHeader.iColor)
   840 		return TUint8(GetRgbPixelEx(aX,aScanlinePtr)._Gray256());
   841 	else
   842 		{
   843 		if (!aScanlinePtr)
   844 			return 0;
   845 
   846 		if (aX >= iHeader.iSizeInPixels.iWidth)
   847 			aX %= iHeader.iSizeInPixels.iWidth;
   848 
   849 		switch (iHeader.iBitsPerPixel)
   850 			{
   851 			case 2:
   852 				{
   853 				TUint32 col = *(aScanlinePtr+(aX>>4));
   854 				col>>=((aX&0xf)<<1);
   855 				col&=3;
   856 				col |= (col << 6) | (col<<4) | (col<<2);
   857 				return TUint8(col);
   858 				}
   859 			case 4:
   860 				{
   861 				TUint32 col = *(aScanlinePtr+(aX>>3));
   862 				col >>= ((aX&7)<<2);
   863 				col &= 0xf;
   864 				return TUint8(col |= (col << 4));
   865 				}
   866 			case 1:
   867 				{
   868 				TUint32 col = *(aScanlinePtr+(aX>>5));
   869 				if (col&(1<<(aX&0x1f))) return 255 ;
   870 				return 0;
   871 				}
   872 			case 8:
   873 				return *(((TUint8*)aScanlinePtr) + aX);
   874 			default:
   875 				return 0;
   876 			 }
   877 
   878 		}
   879 	}
   880 
   881 TRgb CBitwiseBitmap::GetRgbPixelEx(TInt aX,TUint32* aScanlinePtr) const
   882 	{
   883 	// returns pixel as TRgb
   884 
   885 	if (iHeader.iColor)
   886 		{
   887 		if (!aScanlinePtr)
   888 			return KRgbBlack;
   889 
   890 		if (aX>=iHeader.iSizeInPixels.iWidth)
   891 			aX%=iHeader.iSizeInPixels.iWidth;
   892 
   893 		switch (iHeader.iBitsPerPixel)
   894 			{
   895 			case 32:
   896 				if (iSettings.CurrentDisplayMode() == EColor16MAP)
   897 					return TRgb::_Color16MAP(*(aScanlinePtr + aX));
   898 				else if (iSettings.CurrentDisplayMode() == EColor16MA)
   899 					return TRgb::_Color16MA(*(aScanlinePtr + aX));
   900 				//scanLineBytePointer format: BGR0 - 0RGB as INT32.
   901 				else
   902 					return TRgb::_Color16MU(*(aScanlinePtr + aX));
   903 			case 24:
   904 				{
   905 				TUint8* scanLineBytePointer = (TUint8*)aScanlinePtr + aX * 3;
   906 				TInt color16M = *scanLineBytePointer++;
   907 				color16M |= (*scanLineBytePointer++) << 8;
   908 				color16M |= (*scanLineBytePointer++) << 16;
   909 				return TRgb::_Color16M(color16M);
   910 				}
   911 			case 16:
   912 				return TRgb::_Color64K(*(((TUint16*)aScanlinePtr) + aX));
   913 			case 12:
   914 				return TRgb::_Color4K(*(((TUint16*)aScanlinePtr) + aX));
   915 			case 8:
   916 				return TRgb::Color256(*((TUint8*)aScanlinePtr + aX));
   917 			case 4:
   918 				{
   919 				TUint8 colorIndex = *((TUint8*)aScanlinePtr + (aX >> 1));
   920 				if (aX & 1)
   921 					colorIndex >>= 4;
   922 				return TRgb::Color16(colorIndex & 0xf);
   923 				}
   924 			default:
   925 				return KRgbBlack;
   926 			}
   927 		}
   928 	else
   929 		return TRgb::_Gray256(GetGrayPixelEx(aX,aScanlinePtr));
   930 	}
   931 
   932 void CBitwiseBitmap::GetRgbPixelExMany(TInt aX,TUint32* aScanlinePtr, TUint32* aDest,TInt aLength) const
   933     {
   934     __ASSERT_DEBUG(aScanlinePtr && aDest, User::Invariant());
   935     __ASSERT_DEBUG(aX      >= 0, User::Invariant());
   936     __ASSERT_DEBUG(aLength >= 0, User::Invariant());
   937     __ASSERT_DEBUG(aX+aLength <= iHeader.iSizeInPixels.iWidth, User::Invariant());
   938 
   939     union {
   940         TUint8*  scanPtr8;
   941         TUint16* scanPtr16;
   942         TUint32* scanPtr32;
   943     };
   944     TUint32 color;
   945     TUint32 rawData;
   946     const TUint32 opaqueAlpha = 0xff000000;
   947     TUint32 color16MA = 0;  // // cached map to color
   948 
   949     if (aLength < 1)
   950         {
   951         return;
   952         }
   953 
   954     if (iHeader.iColor)
   955         {
   956         switch (iHeader.iBitsPerPixel)
   957             {
   958             case 4:
   959                 {
   960                 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr);
   961                 TUint32 color16 = EFirstTime; // map source color: 16 color mode
   962                 do
   963                     {
   964                     rawData = (aX & 1) ? (scanPtr8[aX >> 1] >> 4) : (scanPtr8[aX >> 1] &0x0F);
   965                     if ((rawData != color16))
   966                         { // first pixel or colour change
   967                         color16MA = TRgb::Color16(rawData)._Color16MA();
   968                         color16 = rawData;
   969                         }
   970                     *aDest++ = color16MA;
   971                     aX++;
   972                     }
   973                     while (--aLength);
   974                 return;
   975                 }
   976             case 8:
   977                 {
   978                 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
   979                 const TUint32* lookup = DynamicPalette::DefaultColor256Util()->iColorTable;
   980                 TUint32 color256 = EFirstTime; // map source color: 256 color
   981                 do
   982                     {
   983                     rawData = *scanPtr8++;
   984                     if ((rawData != color256))
   985                         { // colour change or first pixel
   986                         color16MA = lookup[rawData];
   987                         color256 = rawData;
   988                         // translate between bgr & rgb
   989                         color16MA = ((color16MA & 0x0000ff) << 16) | (color16MA & 0x00ff00) | ((color16MA & 0xff0000) >> 16) | opaqueAlpha;
   990                         }
   991                     *aDest++ = color16MA;
   992                     }
   993                     while (--aLength);
   994                 return;
   995                 }
   996             case 12:
   997                 {
   998                 scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
   999                 TUint32 color4K = EFirstTime; // map source color: 4K color black => 16M color black
  1000                 do
  1001                     {
  1002                     rawData = *scanPtr16++;
  1003                     if ((rawData != color4K))
  1004                         { // colour change
  1005                         color16MA = TRgb::_Color4K(rawData)._Color16MA();
  1006                         color4K = rawData;
  1007                         }
  1008                     *aDest++ = color16MA;
  1009                     }
  1010                     while (--aLength);
  1011                 return;
  1012                 }
  1013             case 16:
  1014                 {
  1015                 scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
  1016                 const TUint16* lowAdd = Convert16to32bppLow();
  1017                 const TUint32* highAdd = Convert16to32bppHigh();
  1018                 TUint32 color64K = EFirstTime; // map source color: 64K color black => 16M color black
  1019                 do
  1020                     {
  1021                     rawData = *scanPtr16++;
  1022                     if ((rawData != color64K))
  1023                         { // colour change
  1024                         color16MA = highAdd[rawData >> 8] | lowAdd[rawData & 0x00FF];
  1025                         color64K = rawData;
  1026                         }
  1027                     *aDest++ = color16MA;
  1028                     }
  1029                     while (--aLength);
  1030                 return;
  1031                 }
  1032             case 24:
  1033                 {
  1034                 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX*3;
  1035                 do
  1036                     {
  1037                     if ((aLength < 4) || (3 & (TUint32)(scanPtr8)))
  1038                         {
  1039                         aLength--;
  1040                         color  =  *scanPtr8++;
  1041                         color |= (*scanPtr8++) << 8;
  1042                         color |= (*scanPtr8++) << 16;
  1043                         *aDest++ = color | opaqueAlpha;
  1044                         }
  1045                     else
  1046                         { // source is now TUint32 aligned - so read source as blocks of 3 TUint32's & write as 4
  1047                         TUint32 word1, word2, word3;
  1048                         TInt iter = (aLength / 4) - 1;
  1049                         aLength = aLength & 0x0003;
  1050                         do
  1051                             {
  1052                             word1 = *scanPtr32++; 
  1053                             *aDest++ = word1 | opaqueAlpha;
  1054                             word2 = *scanPtr32++; 
  1055                             color = (word1 >> 24) | ((word2 & 0xFFFF) << 8); 
  1056                             *aDest++ = color | opaqueAlpha;
  1057                             word3 = *scanPtr32++; 
  1058                             color = (word2 >> 16) | ((word3 & 0x00FF) << 16); 
  1059                             *aDest++ = color | opaqueAlpha;
  1060                             *aDest++ = (word3 >> 8) | opaqueAlpha;
  1061                             }
  1062                             while (iter--);
  1063                         }
  1064                     }
  1065                     while (aLength);
  1066                 return;
  1067                 }
  1068             case 32:
  1069                 {
  1070                 scanPtr32 = aScanlinePtr + aX;
  1071                 if(iSettings.CurrentDisplayMode() == EColor16MAP)
  1072                     { // unrolled loop uses "Duff's Device"
  1073                     const TUint16* normTable = PtrTo16BitNormalisationTable();
  1074                     --aLength;
  1075                     TInt iter = aLength / 8;
  1076                     switch(aLength & 7) 
  1077                         {
  1078                         case 7:
  1079                             do {
  1080                                 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1081                         case 6:
  1082                                 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1083                         case 5:
  1084                                 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1085                         case 4:
  1086                                 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1087                         case 3:
  1088                                 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1089                         case 2:
  1090                                 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1091                         case 1:
  1092                                 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1093                         case 0:
  1094                                 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1095                             } while (iter-- > 0);
  1096                         }
  1097                     }
  1098                 else if (iSettings.CurrentDisplayMode() == EColor16MU)
  1099                     { // unrolled loop uses "Duff's Device"
  1100                     --aLength;
  1101                     TInt iter = aLength / 8;
  1102                     switch(aLength & 7) 
  1103                         {
  1104                         case 7:
  1105                             do {
  1106                                 *aDest++ = (*scanPtr32++) | opaqueAlpha;
  1107                         case 6:
  1108                                 *aDest++ = (*scanPtr32++) | opaqueAlpha;
  1109                         case 5:
  1110                                 *aDest++ = (*scanPtr32++) | opaqueAlpha;
  1111                         case 4:
  1112                                 *aDest++ = (*scanPtr32++) | opaqueAlpha;
  1113                         case 3:
  1114                                 *aDest++ = (*scanPtr32++) | opaqueAlpha;
  1115                         case 2:
  1116                                 *aDest++ = (*scanPtr32++) | opaqueAlpha;
  1117                         case 1:
  1118                                 *aDest++ = (*scanPtr32++) | opaqueAlpha;
  1119                         case 0:
  1120                                 *aDest++ = (*scanPtr32++) | opaqueAlpha;
  1121                             } while (iter-- > 0);
  1122                         }
  1123                     }
  1124                 else // EColor16MA
  1125                     {
  1126                     Mem::Move(aDest, scanPtr32, aLength * 4);
  1127                     }
  1128                 return;
  1129                 }
  1130             default:
  1131                 return;
  1132             }
  1133         }
  1134     else
  1135         {
  1136         switch (iHeader.iBitsPerPixel)
  1137             {
  1138             case 1:
  1139                 {
  1140                 do
  1141                     {
  1142                     *aDest++ = TUint32(COLOR_VALUE(aScanlinePtr, aX) ? 0xFFFFFFFF : 0xFF000000);
  1143                     aX++;
  1144                     }
  1145                 while (--aLength);
  1146                 break;
  1147                 }
  1148             case 8:
  1149                 {
  1150                 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
  1151                 do
  1152                     {
  1153                     rawData = *scanPtr8++;
  1154                     color16MA = rawData | (rawData << 8) | (rawData << 16) | opaqueAlpha; 
  1155                     *aDest++ = color16MA;
  1156                     }
  1157                     while (--aLength);              
  1158                 break;
  1159                 }
  1160             default:
  1161                 {
  1162                 do
  1163                     {
  1164                     rawData = GetGrayPixelEx(aX++,aScanlinePtr);
  1165                     color16MA = rawData | (rawData << 8) | (rawData << 16) | opaqueAlpha; 
  1166                     *aDest++ = color16MA;
  1167                     }
  1168                     while (--aLength);              
  1169                 }
  1170             }
  1171         }
  1172     }
  1173 /**
  1174 The method retrieves the RGB color values from the scanline, and converts them
  1175 into the destination screen-mode pixel format. This method handles the special
  1176 case when the destination mode is EColor16MAP (32bit with alpha values premultiplied
  1177 with the color channels. Calls GetRgbPixelExMany for values not 32 bit, as there is no
  1178 alpha information in these color modes. For color mode EColor16MU, no conversion is 
  1179 performed (as alpha is assumed to be 1).
  1180 @internalComponent
  1181 @released
  1182 @param aX	The x co-ordinate the scanline data needs to be retrieved from.
  1183 @param aScanlinePtr	The scanline pointer, i.e. the source data.
  1184 @param aDest	The pointer to the destination buffer. This is where the output is stored.
  1185 @param aLength	The number of bytes to be copied. This value must be a multiple of 4.
  1186 */
  1187 void CBitwiseBitmap::GetRgbPixelExMany16MAP(TInt aX,TUint32* aScanlinePtr,TUint32* aDest,TInt aLength) const
  1188     {
  1189     __ASSERT_DEBUG(aScanlinePtr && aDest, User::Invariant());
  1190     __ASSERT_DEBUG(aX      >= 0, User::Invariant());
  1191     __ASSERT_DEBUG(aLength >= 0, User::Invariant());
  1192     __ASSERT_DEBUG(aX+aLength <= iHeader.iSizeInPixels.iWidth, User::Invariant());
  1193 
  1194     TUint32* scanPtr32;
  1195 
  1196     if ((iHeader.iColor) && (iHeader.iBitsPerPixel == 32))
  1197         {
  1198         scanPtr32 = aScanlinePtr + aX;
  1199         if (DisplayMode() == EColor16MAP)
  1200             {
  1201             Mem::Move(aDest, scanPtr32, aLength<<2);
  1202             }
  1203         else if(DisplayMode()==EColor16MA)
  1204             {
  1205             TUint32* ptrLimit = aDest + aLength;
  1206             const TInt32 zero = 0;
  1207             while (aDest < ptrLimit)
  1208                 {
  1209                 TUint32 value = *scanPtr32++;
  1210                 TUint32 tA = value >> 24;
  1211                 if (tA == 0)
  1212                     {
  1213                     *aDest++ = zero;
  1214                     }
  1215                 else if (tA != 255) 
  1216                     {
  1217                     *aDest++ = NonPMA2PMAPixel(value);
  1218                     }
  1219                 else
  1220                     {
  1221                     *aDest++ = value;
  1222                     }
  1223                 }
  1224             }
  1225         else // DisplayMode() == EColor16MU
  1226             {
  1227             if (aLength--)
  1228                 { // unrolled loop uses "Duff's Device"
  1229                 const TUint32 alpha = 0xFF000000;   //set all the alpha to 0xff
  1230                 TInt iter = aLength / 8;
  1231                 switch(aLength & 7) 
  1232                     {
  1233                     case 7:
  1234                         do {
  1235                             *aDest++ = (*scanPtr32++) | alpha;
  1236                     case 6:
  1237                             *aDest++ = (*scanPtr32++) | alpha;
  1238                     case 5:
  1239                             *aDest++ = (*scanPtr32++) | alpha;
  1240                     case 4:
  1241                             *aDest++ = (*scanPtr32++) | alpha;
  1242                     case 3:
  1243                             *aDest++ = (*scanPtr32++) | alpha;
  1244                     case 2:
  1245                             *aDest++ = (*scanPtr32++) | alpha;
  1246                     case 1:
  1247                             *aDest++ = (*scanPtr32++) | alpha;
  1248                     case 0:
  1249                             *aDest++ = (*scanPtr32++) | alpha;
  1250                         } while (iter-- > 0);
  1251                     }
  1252                 }
  1253             }
  1254         }
  1255     else
  1256         {
  1257         GetRgbPixelExMany(aX, aScanlinePtr, aDest, aLength);
  1258         }
  1259     }
  1260 
  1261 void CBitwiseBitmap::GetRgbPixelExMany16M(TInt aX,TUint32* aScanlinePtr, TUint8* aDest,TInt aLength) const
  1262     {
  1263     union {
  1264         TUint8*  scanPtr8;
  1265         TUint16* scanPtr16;
  1266         TUint32* scanPtr32;
  1267     };
  1268     union {
  1269         TUint8*  destPtr8;
  1270         TUint32* destPtr32;
  1271     };
  1272     destPtr8 = aDest;
  1273     TUint32 rawData;
  1274 
  1275     if (!aScanlinePtr)
  1276         {
  1277         const TUint32 zero = 0; // conveniently KRgbBlack is 0 in EColor16M mode
  1278         while (aLength)
  1279             {
  1280             if ((aLength < 4) || (3 & (TUint32)(destPtr8)))
  1281                 {
  1282                 aLength--;
  1283                 *destPtr8++ = zero;
  1284                 *destPtr8++ = zero;
  1285                 *destPtr8++ = zero;
  1286                 }
  1287             else
  1288                 { // dest is now TUint32 aligned - write 4 pixels into 3 TUint32s
  1289                 aLength -= 4;
  1290                 *destPtr32++ = zero;
  1291                 *destPtr32++ = zero;
  1292                 *destPtr32++ = zero;
  1293                 }
  1294             }
  1295         return;
  1296         }
  1297 
  1298     if (aX>=iHeader.iSizeInPixels.iWidth)
  1299         {
  1300         aX%=iHeader.iSizeInPixels.iWidth;
  1301         }
  1302 
  1303     while (aLength)
  1304         {
  1305         // cached map to color
  1306         TUint32 color16M = 0;
  1307         TInt copyLength = iHeader.iSizeInPixels.iWidth - aX;
  1308         TUint32* scanPtr32 = aScanlinePtr + aX;
  1309         if (copyLength > aLength)
  1310             {
  1311             copyLength = aLength;
  1312             }
  1313         aLength -= copyLength;
  1314 
  1315         if (iHeader.iColor)
  1316             {
  1317             switch(iHeader.iBitsPerPixel)
  1318                 {
  1319                 case 4:
  1320                     {
  1321                     scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr);
  1322                     TUint32 color16 = EFirstTime; // map source color: 16 color mode
  1323                     do
  1324                         {
  1325                         rawData = (aX & 1) ? (scanPtr8[aX >> 1] >> 4) : (scanPtr8[aX >> 1] &0x0F);
  1326                         if ((rawData != color16))
  1327                             { // first pixel or colour change
  1328                             color16M = TRgb::Color16(rawData)._Color16M();
  1329                             color16 = rawData;
  1330                             }
  1331                         *destPtr8++ = TUint8(color16M);
  1332                         *destPtr8++ = TUint8(color16M >> 8);
  1333                         *destPtr8++ = TUint8(color16M >> 16);
  1334                         aX++;
  1335                         }
  1336                         while (--copyLength);
  1337                     break;
  1338                     }
  1339                 case 8:
  1340                     {
  1341                     scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
  1342                     const TUint32* lookup = DynamicPalette::DefaultColor256Util()->iColorTable;
  1343                     TUint32 color256 = EFirstTime; // map source color: 256 color
  1344                     do
  1345                         {
  1346                         rawData = *scanPtr8++;
  1347                         if ((rawData != color256))
  1348                             { // first pixel or colour change; so perform new mapping
  1349                             color16M = lookup[rawData];
  1350                             color256 = rawData;
  1351                             }
  1352                         // Note; byte order performs required bgr -> rgb conversion 
  1353                         *destPtr8++ = TUint8(color16M >> 16);
  1354                         *destPtr8++ = TUint8(color16M >> 8);
  1355                         *destPtr8++ = TUint8(color16M);
  1356                         }
  1357                         while (--copyLength);
  1358                     break;
  1359                     }
  1360                 case 12:
  1361                     {
  1362                     scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
  1363                     TUint32 color4K = EFirstTime; // map source color: 4K color black => 16M color black
  1364                     do
  1365                         {
  1366                         rawData = *scanPtr16++;
  1367                         if ((rawData != color4K))
  1368                             { // first pixel or colour change
  1369                             color16M = TRgb::_Color4K(rawData)._Color16M();
  1370                             color4K = rawData;
  1371                             }
  1372                         *destPtr8++ = TUint8(color16M);
  1373                         *destPtr8++ = TUint8(color16M >> 8);
  1374                         *destPtr8++ = TUint8(color16M >> 16);
  1375                         }
  1376                         while (--copyLength);
  1377                     break;
  1378                     }
  1379                 case 16:
  1380                     {
  1381                     scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
  1382                     const TUint16* lowAdd = Convert16to32bppLow();
  1383                     const TUint32* highAdd = Convert16to32bppHigh();
  1384                     TUint16 halfWord;
  1385                     TUint32 color64K = EFirstTime; // 64K color black => 16M color black
  1386                     color16M = 0;
  1387                     do
  1388                         {
  1389                         halfWord = *scanPtr16++;
  1390                         if ((halfWord != color64K))
  1391                             { // colour change
  1392                             color16M = highAdd[halfWord >> 8] | lowAdd[halfWord & 0x00FF];
  1393                             color64K = halfWord;
  1394                             }
  1395                         *destPtr8++ = TUint8(color16M);
  1396                         *destPtr8++ = TUint8(color16M >> 8);
  1397                         *destPtr8++ = TUint8(color16M >> 16);
  1398                         }
  1399                         while (--copyLength);
  1400                     break;
  1401                     }
  1402                 case 24:
  1403                     {
  1404                     Mem::Copy(destPtr8, reinterpret_cast<TUint8*>(aScanlinePtr) + aX, copyLength * 3); // may not be aligned 
  1405                     destPtr8 += copyLength * 3;
  1406                     break;
  1407                     }
  1408                 case 32:
  1409                     {
  1410                     scanPtr32 = aScanlinePtr + aX;
  1411                     if (iSettings.CurrentDisplayMode() == EColor16MAP)
  1412                         {
  1413                         const TUint16* normTable = PtrTo16BitNormalisationTable();
  1414                         do
  1415                             {
  1416                             // convert from EColor16MAP to EColor16MA first.
  1417                             color16M = PMA2NonPMAPixel(*scanPtr32++, normTable);
  1418                             *destPtr8++ = TUint8(color16M);
  1419                             *destPtr8++ = TUint8(color16M >> 8);
  1420                             *destPtr8++ = TUint8(color16M >> 16);
  1421                             }
  1422                             while (--copyLength);
  1423                         }
  1424                     else
  1425                         { // EColor16MA or EColor16MU, keep the RGB & throw away the top byte
  1426                         // scanLineBytePointer format: ARGB - 0RGB as INT32 or BGR0 - 0RGB as INT32.
  1427                         do
  1428                             {
  1429                             if ((copyLength < 4) || (3 & (TUint32)destPtr8))
  1430                                 {
  1431                                 color16M = *scanPtr32++;
  1432                                 --copyLength;
  1433                                 *destPtr8++ = TUint8(color16M);
  1434                                 *destPtr8++ = TUint8(color16M >> 8);
  1435                                 *destPtr8++ = TUint8(color16M >> 16);
  1436                                 }
  1437                             else // dest is TUint32 aligned: copy 4 pixels into 3 TUint32's
  1438                                 {
  1439                                 color16M = (*scanPtr32++) & 0x00FFFFFF;
  1440                                 rawData = (*scanPtr32++) & 0x00FFFFFF;
  1441                                 copyLength -= 4;
  1442                                 *destPtr32++ = color16M | (rawData << 24);
  1443                                 color16M = (*scanPtr32++) & 0x00FFFFFF;
  1444                                 *destPtr32++ = (color16M << 16) | (rawData >> 8);
  1445                                 rawData = (*scanPtr32++) & 0x00FFFFFF;
  1446                                 *destPtr32++ = (color16M >> 16) | (rawData << 8);
  1447                                 }
  1448                             }
  1449                             while (copyLength);
  1450                         }
  1451                     break;
  1452                     }
  1453                 default:
  1454                     break;
  1455                 }
  1456             }
  1457         else
  1458             { // !iHeader.iColor
  1459             if (iHeader.iBitsPerPixel == 8)
  1460                 {
  1461                 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
  1462                 do
  1463                     {
  1464                     rawData = *scanPtr8++;
  1465                     *destPtr8++ = (TUint8)rawData;
  1466                     *destPtr8++ = (TUint8)rawData;
  1467                     *destPtr8++ = (TUint8)rawData;
  1468                     }
  1469                     while (--copyLength);
  1470                 }
  1471             else
  1472                 {
  1473                 do
  1474                     {
  1475                     rawData = GetGrayPixelEx(aX++,aScanlinePtr);
  1476                     *destPtr8++ = (TUint8)rawData;
  1477                     *destPtr8++ = (TUint8)rawData;
  1478                     *destPtr8++ = (TUint8)rawData;
  1479                     }
  1480                     while (--copyLength);
  1481                 }
  1482             }
  1483         aX = 0; // second copy, if any, comes from start of line
  1484         }
  1485 
  1486     return;
  1487     }
  1488 
  1489 void CBitwiseBitmap::GenerateLineFromCompressedEightBitData(TUint8* aDestBuffer, const TPoint& aPixel,TInt aLength, TUint32* aBase,TLineScanningPosition& aLineScanningPosition) const
  1490 	{
  1491 	const TInt bitmapWidth=iByteWidth;
  1492 	const TInt pixelsPerByte=8/iHeader.iBitsPerPixel;
  1493 	const TInt startPos=aPixel.iY*bitmapWidth+aPixel.iX/pixelsPerByte;
  1494 	const TInt endPos=aPixel.iY*bitmapWidth+(aPixel.iX+aLength+pixelsPerByte-1)/pixelsPerByte;
  1495 	const TInt byteLength=endPos-startPos;
  1496 	TInt writes=byteLength;
  1497 	TUint8* destPtr = ((TUint8*)aDestBuffer);
  1498 	destPtr+=(aPixel.iX/pixelsPerByte);
  1499 	if (aLineScanningPosition.iCursorPos>startPos)
  1500 		{
  1501 		aLineScanningPosition.iSrcDataPtr=(TUint8*)aBase;
  1502 		aLineScanningPosition.iCursorPos=0;
  1503 		}
  1504 	TUint8* srcePtr = (TUint8*)aLineScanningPosition.iSrcDataPtr;
  1505 	TInt8 count=*srcePtr;
  1506 	TInt16 addition;
  1507 	if (count<0)
  1508 		addition=(TInt16) (-count);
  1509 	else
  1510 		addition=(TInt16) (count+1);
  1511 	while (aLineScanningPosition.iCursorPos+addition<startPos)
  1512 		{
  1513 		aLineScanningPosition.iCursorPos+=addition;
  1514 		if (count<0)
  1515 			{
  1516 			srcePtr+=(-count+1);
  1517 			}
  1518 		else
  1519 			{
  1520 			srcePtr+=2;  // Just skip over value
  1521 			}
  1522 		count = *srcePtr;
  1523 		if (count<0)
  1524 			addition=(TInt16) (-count);
  1525 		else
  1526 			addition=(TInt16) (count+1);
  1527 		}
  1528 	// Then scan the line
  1529 	count=0;
  1530 	while (aLineScanningPosition.iCursorPos+count<startPos+byteLength)
  1531 		{
  1532 		TBool negativeCount=EFalse;
  1533 		count=*srcePtr;
  1534 		if (count<0)
  1535 			{
  1536 			negativeCount=ETrue;
  1537 			count=(TInt8) ((-count)-1);
  1538 			}
  1539 		TUint8 value = *(srcePtr+1);
  1540 		TInt distanceToTheLineEnd=startPos+byteLength-aLineScanningPosition.iCursorPos;
  1541 		if (count<distanceToTheLineEnd)
  1542 			{
  1543 			if (!negativeCount)
  1544 				{
  1545 				srcePtr+=2;
  1546 				}
  1547 			else
  1548 				{
  1549 				srcePtr+=1;
  1550 				}
  1551 			TInt countPlusOne = (TInt)count + 1;
  1552 			TInt start = Max(0,startPos-aLineScanningPosition.iCursorPos);
  1553 			if (countPlusOne > start)
  1554 				{
  1555 				TInt length = Min(countPlusOne-start,writes);
  1556 				writes -= countPlusOne-start;
  1557 				if (length > 0)
  1558 					{
  1559 					/*Mem::Fill and Mem::Copy used in order to increase the performance*/
  1560 					if (!negativeCount)
  1561 						{
  1562 						Mem::Fill(destPtr,length,value);
  1563 						}
  1564 					else
  1565 						{
  1566 						Mem::Copy(destPtr,srcePtr+start,length);
  1567 						}
  1568 					destPtr += length;
  1569 					}
  1570 				}
  1571 			if (negativeCount)
  1572 				{
  1573 				srcePtr += countPlusOne;
  1574 				}
  1575 			aLineScanningPosition.iCursorPos += countPlusOne;
  1576 			count=0;
  1577 			}
  1578 			else
  1579 			{
  1580 			TInt correction=1;
  1581 			if (aLineScanningPosition.iCursorPos<startPos)
  1582 				{
  1583 				correction=startPos-aLineScanningPosition.iCursorPos+1;
  1584 				}
  1585 			TInt length = Min(byteLength,writes);
  1586 			writes -= length;
  1587 			/*Mem::Fill and Mem::Copy used in order to increase the performance*/
  1588 			if (!negativeCount)
  1589 				{
  1590 				Mem::Fill(destPtr,length,value);
  1591 				}
  1592 			else
  1593 				{
  1594 				Mem::Copy(destPtr,srcePtr+correction,length);
  1595 				}
  1596 			destPtr += length;
  1597 			}
  1598 		}
  1599 	aLineScanningPosition.iSrcDataPtr=(TUint8*) srcePtr;
  1600 	}
  1601 
  1602 void CBitwiseBitmap::GenerateLineFromCompressedTwelveBitData(TUint8* aDestBuffer, const TPoint& aPixel,TInt aLength, TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
  1603 	{
  1604 	const TInt bitmapWidth=iByteWidth>>1;
  1605 	const TInt startPos=aPixel.iY*bitmapWidth+aPixel.iX;
  1606 	TInt writes=aLength*2;
  1607 	TUint16* destPtr = ((TUint16*)aDestBuffer);//+aPixel.iX;
  1608 	destPtr+=aPixel.iX;
  1609 
  1610 	if(iPile)
  1611 		{
  1612 		::AdjustLineScanningPosition(aLineScanningPosition, aBase, bitmapWidth, startPos, iHeader.iBitmapSize - sizeof(SEpocBitmapHeader));
  1613 		}
  1614 	TUint16* srcePtr = (TUint16*)aLineScanningPosition.iSrcDataPtr;
  1615 
  1616 	// Fast find the correct position to start
  1617 	TInt count=0;
  1618 	if(::Abs(aLineScanningPosition.iCursorPos - startPos) > startPos)
  1619 		{
  1620 		srcePtr = (TUint16*)aBase;
  1621 		aLineScanningPosition.iCursorPos = 0;
  1622 		}
  1623 	while (aLineScanningPosition.iCursorPos>startPos)
  1624 		{
  1625 		srcePtr--;
  1626 		TUint16 value = *srcePtr;
  1627 		count = value >> 12;
  1628 		aLineScanningPosition.iCursorPos-=(count+1);
  1629 		}
  1630 	while (aLineScanningPosition.iCursorPos<startPos)
  1631 		{
  1632 		TUint16 value = *srcePtr++;
  1633 		count = value >> 12;
  1634 		aLineScanningPosition.iCursorPos+=count+1;
  1635 		}
  1636 	if (aLineScanningPosition.iCursorPos>startPos)
  1637 		{
  1638 		aLineScanningPosition.iCursorPos-=(count+1);
  1639 		srcePtr--;
  1640 		}
  1641 
  1642 	// Then scan the line
  1643 	count=0;
  1644 	while (aLineScanningPosition.iCursorPos+count<startPos+aLength)
  1645 		{
  1646 		TUint16 value = *srcePtr;
  1647 		count = value >> 12;
  1648 		value &= 0x0fff;
  1649 		TInt distanceToTheLineEnd=startPos+aLength-aLineScanningPosition.iCursorPos;
  1650 		if (count<distanceToTheLineEnd)
  1651 			{
  1652 			srcePtr++;
  1653 			for (TInt ii=0 ; ii<=count ; ii++)
  1654 				{
  1655 				if (aLineScanningPosition.iCursorPos>=startPos)
  1656 					{
  1657 					if (writes>0)
  1658 						*destPtr++ = value;
  1659 					writes-=2;
  1660 					}
  1661 				aLineScanningPosition.iCursorPos++;
  1662 
  1663 				}
  1664 			count=0;
  1665 			}
  1666 		else
  1667 			{
  1668 			for (TInt ii=0 ; ii<distanceToTheLineEnd ; ii++)
  1669 				{
  1670 				writes-=2;
  1671 				*destPtr++ = value;
  1672 				if (writes==0)
  1673 					break;
  1674 				}
  1675 			}
  1676 		}
  1677 	aLineScanningPosition.iSrcDataPtr=(TUint8*) srcePtr;
  1678 	}
  1679 
  1680 /**
  1681 The method generates a line from compressed 16 bpp bitmap data.
  1682 @internalComponent
  1683 @see TScanLineDecompressor
  1684 */
  1685 void CBitwiseBitmap::GenerateLineFromCompressedSixteenBitData(TUint8* aDestBuffer,
  1686 															  const TPoint& aPixel,
  1687 															  TInt aLength,
  1688 															  TUint32* aBase,
  1689 															  TLineScanningPosition& aLineScanningPosition) const
  1690 	{
  1691 	TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
  1692 	TScanLineDecompressor<E2bpp, E2bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
  1693 	decompr(aDestBuffer, aPixel, aLineScanningPosition, iByteWidth, iByteWidth, aLength);
  1694 	}
  1695 
  1696 /**
  1697 The method generates a line from compressed 24 bpp bitmap data.
  1698 @internalComponent
  1699 @see TScanLineDecompressor
  1700 */
  1701 void CBitwiseBitmap::GenerateLineFromCompressed24BitData(
  1702 									 TUint8* aDestBuffer,
  1703 									 const TPoint& aPixel,
  1704 									 TInt aLength,
  1705 									 TUint32* aBase,
  1706 									 TLineScanningPosition& aLineScanningPosition) const
  1707 	{
  1708 	TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
  1709 	TScanLineDecompressor<E3bpp, E3bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
  1710 	decompr(aDestBuffer, aPixel, aLineScanningPosition, iByteWidth, iByteWidth, aLength);
  1711 	}
  1712 
  1713 /**
  1714 The method generates a line from compressed 24 bpp to 32 bpp bitmap data .
  1715 @internalComponent
  1716 @see TScanLineDecompressor
  1717 */
  1718 void CBitwiseBitmap::GenerateLineFromCompressed32UBitData(
  1719 									 TUint8* aDestBuffer,
  1720 									 const TPoint& aPixel,
  1721 									 TInt aLength,
  1722 									 TUint32* aBase,
  1723 									 TLineScanningPosition& aLineScanningPosition) const
  1724 	{
  1725 	TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
  1726 	TScanLineDecompressor<E3bpp, E4bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
  1727 
  1728 	TUint32 theByteWidthSrc = iHeader.iSizeInPixels.iWidth * 3;
  1729 	decompr(aDestBuffer, aPixel, aLineScanningPosition, theByteWidthSrc, iByteWidth, aLength);
  1730 	}
  1731 
  1732 /**
  1733 The method generates a line from compressed 32 bpp to 32 bpp bitmap data .
  1734 @internalComponent
  1735 @see TScanLineDecompressor
  1736 */
  1737 void CBitwiseBitmap::GenerateLineFromCompressed32ABitData(
  1738  									 TUint8* aDestBuffer,
  1739  									 const TPoint& aPixel,
  1740  									 TInt aLength,
  1741  									 TUint32* aBase,
  1742  									 TLineScanningPosition& aLineScanningPosition) const
  1743 	{
  1744 	TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
  1745 	TScanLineDecompressor<E4bpp, E4bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
  1746 
  1747 	TUint32 theByteWidthSrc = iHeader.iSizeInPixels.iWidth * 4;
  1748 	decompr(aDestBuffer, aPixel, aLineScanningPosition, theByteWidthSrc, iByteWidth, aLength);
  1749 	}
  1750 
  1751 TInt CBitwiseBitmap::DoGetScanLinePtr(TUint32*& aSlptr, TPoint& aPixel,TInt aLength,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
  1752 	{
  1753 	TUint8* buf=NULL;
  1754 	HBufC8* hBuf=aLineScanningPosition.iScanLineBuffer;
  1755 	if (!hBuf)
  1756 		{
  1757 		RFbsSession* session=RFbsSession::GetSession();
  1758 		if (session)
  1759 			{
  1760 			hBuf=session->GetScanLineBuffer();
  1761 			}
  1762 		else
  1763 			{
  1764 			aSlptr=NULL;
  1765 			return KErrSessionClosed;
  1766 			}
  1767 		aLineScanningPosition.iScanLineBuffer=hBuf;
  1768 		}
  1769 	__ASSERT_ALWAYS(hBuf && hBuf->Des().MaxLength() >= iByteWidth, User::Invariant());
  1770 	buf = const_cast<TUint8*>(hBuf->Ptr());
  1771 	switch(iHeader.iCompression)
  1772 		{
  1773 		case ETwelveBitRLECompression:
  1774 			GenerateLineFromCompressedTwelveBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
  1775 			break;
  1776 		case EByteRLECompression:
  1777 			GenerateLineFromCompressedEightBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
  1778 			break;
  1779 		case ESixteenBitRLECompression:
  1780 			GenerateLineFromCompressedSixteenBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
  1781 			break;
  1782 		case ETwentyFourBitRLECompression:
  1783 			GenerateLineFromCompressed24BitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
  1784 			break;
  1785 		case EThirtyTwoUBitRLECompression:
  1786 			GenerateLineFromCompressed32UBitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
  1787 			break;
  1788 		case EThirtyTwoABitRLECompression:
  1789 			GenerateLineFromCompressed32ABitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
  1790 			break;
  1791 		case EGenericPaletteCompression:
  1792 			GenerateLineFromPaletteCompressedData(buf, aPixel, aLength, aBase, aLineScanningPosition);
  1793 			break;
  1794 		case EProprietaryCompression:
  1795 			if (aLineScanningPosition.iRasterizer)
  1796 				{
  1797 				aSlptr = const_cast<TUint32*>(aLineScanningPosition.iRasterizer->ScanLine(Extra()->iSerialNumber, aPixel, aLength));
  1798 				if (aSlptr)
  1799 					{
  1800 					return KErrNone;
  1801 					}
  1802 				}
  1803 			WhiteFill(buf, iByteWidth, iSettings.CurrentDisplayMode());
  1804 			break;
  1805 		default:
  1806 			{
  1807 			__ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
  1808 			return KErrNotSupported;
  1809 			}
  1810 		}
  1811 	aSlptr = (TUint32*) buf;
  1812 	return KErrNone;
  1813 	}
  1814 
  1815 EXPORT_C void CBitwiseBitmap::GetScanLine(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase,TLineScanningPosition& aLineScanningPosition) const
  1816 	{
  1817 	if (!iDataOffset)
  1818 		return;
  1819 
  1820 	TPoint pixel(aPixel);
  1821 	TUint32* slptr=NULL;
  1822 	GetScanLinePtr(slptr, aLength, pixel,aBase, aLineScanningPosition);
  1823 	GetScanLine(slptr,aBuf,pixel,aLength,aDither,aDitherOffset,aDispMode);
  1824 	}
  1825 
  1826 EXPORT_C void CBitwiseBitmap::GetScanLine(TUint32*& aScanLinePtr, TDes8& aDestBuf,const TPoint& aPixel,TInt aLength,TBool aDither,
  1827 	const TPoint& aDitherOffset,TDisplayMode aDestinationDispMode) const
  1828 	{
  1829 	if (!iDataOffset)
  1830 		return;
  1831 	TDisplayMode currentDisplayMode = iSettings.CurrentDisplayMode();
  1832 	if (!aScanLinePtr) // if scanline pointer is null,
  1833 		{
  1834 		WhiteFill((TUint8*)aDestBuf.Ptr(),aDestBuf.MaxLength(),currentDisplayMode);
  1835 		return;
  1836 		}
  1837 	TUint8* ptr = (TUint8*)aDestBuf.Ptr();
  1838 	// if dest pointer is not aligned
  1839 	if (!(TUint32(ptr)&3) && aDestinationDispMode == currentDisplayMode)
  1840 		{
  1841 		if (iHeader.iBitsPerPixel < 8)
  1842 			GetScanLineExBits(aDestBuf,aPixel.iX,aLength,aScanLinePtr);
  1843 		else
  1844 			GetScanLineExBytes(aDestBuf,aPixel.iX,aLength,aScanLinePtr);
  1845 		return;
  1846 		}
  1847 	//read the scanline in destination display format.
  1848 	switch (aDestinationDispMode)
  1849 		{
  1850 	case EGray2:
  1851 		GetScanLineGray2(aDestBuf,aPixel,aLength,aDither,aDitherOffset,aScanLinePtr);
  1852 		break;
  1853 	case EGray4:
  1854 		GetScanLineGray4(aDestBuf,aPixel,aLength,aDither,aDitherOffset,aScanLinePtr);
  1855 		break;
  1856 	case EGray16:
  1857 		GetScanLineGray16(aDestBuf,aPixel,aLength,aScanLinePtr);
  1858 		break;
  1859 	case EGray256:
  1860 		GetScanLineGray256(aDestBuf,aPixel,aLength,aScanLinePtr);
  1861 		break;
  1862 	case EColor16:
  1863 		GetScanLineColor16(aDestBuf,aPixel,aLength,aScanLinePtr);
  1864 		break;
  1865 	case EColor256:
  1866 		GetScanLineColor256(aDestBuf,aPixel,aLength,aScanLinePtr);
  1867 		break;
  1868 	case EColor4K:
  1869 		GetScanLineColor4K(aDestBuf,aPixel,aLength,aScanLinePtr);
  1870 		break;
  1871 	case EColor64K:
  1872 		GetScanLineColor64K(aDestBuf,aPixel,aLength,aScanLinePtr);
  1873 		break;
  1874 	case EColor16M:
  1875 		GetScanLineColor16M(aDestBuf,aPixel,aLength,aScanLinePtr);
  1876 		break;
  1877 	case ERgb:
  1878 		GetScanLineColorRgb(aDestBuf,aPixel,aLength,aScanLinePtr);
  1879 		break;
  1880 	case EColor16MU:
  1881 		GetScanLineColor16MU(aDestBuf,aPixel,aLength,aScanLinePtr);
  1882 		break;
  1883 	case EColor16MA:
  1884 		GetScanLineColor16MA(aDestBuf,aPixel,aLength,aScanLinePtr);
  1885 		break;
  1886 	case EColor16MAP:
  1887 		GetScanLineColor16MAP(aDestBuf,aPixel,aLength,aScanLinePtr);
  1888 		break;
  1889 	default:
  1890 		aDestBuf.SetLength(0);
  1891 		break;
  1892 		};
  1893 	}
  1894 
  1895 EXPORT_C void CBitwiseBitmap::GetScanLine(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase) const
  1896 	{
  1897 	TLineScanningPosition pos(aBase);
  1898 	TUint8* base = REINTERPRET_CAST(TUint8*,aBase);
  1899 	const TCompressionBookMark* bookMarkPtr = NULL;
  1900 
  1901 	GetLineScanPos(pos, bookMarkPtr, base);
  1902 	GetScanLine(aBuf,aPixel,aLength,aDither,aDitherOffset,aDispMode,aBase,pos);
  1903 	UpdateBookMark(pos, const_cast<TCompressionBookMark*>(bookMarkPtr), base);
  1904 	}
  1905 
  1906 /**
  1907 Gets the bitmapís vertical scanline starting at the specified x co-ordinate and using
  1908 the specified dither offset.
  1909 Note: The method works for uncompressed bitmaps only.
  1910 @param aBuf The buffer in which the vertical scanline will be returned.
  1911 @param aX The x co-ordinate of the vertical scanline to get.
  1912 @param aDitherOffset The dither offset of the bitmap.
  1913 @param aDispMode Format to be used to write the data to the buffer.
  1914 @param aBase The bitmap's data start address.
  1915 */
  1916 EXPORT_C void CBitwiseBitmap::GetVerticalScanLine(TDes8& aBuf,TInt aX,TBool aDither,
  1917 												  const TPoint& aDitherOffset,
  1918 												  TDisplayMode aDispMode,
  1919 												  TUint32* aBase,
  1920 												  CFbsRasterizer* aRasterizer) const
  1921 	{
  1922 	if (iHeader.iCompression != ENoBitmapCompression && iHeader.iCompression != EProprietaryCompression)
  1923 		{
  1924 		__ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
  1925 		return; //not supported for compressed bitmaps
  1926 		}
  1927 
  1928 	if (!iDataOffset)
  1929 		{
  1930 		return;
  1931 		}
  1932 	AdjustXCoord(aX);
  1933 	TInt height=iHeader.iSizeInPixels.iHeight;
  1934 	TUint32* slptr=aBase;
  1935 	TUint8* ptr = (TUint8*)aBuf.Ptr();
  1936 	*ptr=0;
  1937 	const TInt wordwidth=iByteWidth>>2;
  1938 	TInt y = 0;
  1939 
  1940 	if (iHeader.iCompression == EProprietaryCompression)
  1941 		{
  1942 		if (aRasterizer)
  1943 			{
  1944 			slptr = const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,0), 1));
  1945 			if (!slptr)
  1946 				{
  1947 				// wrong rasterizer for this extended bitmap - fill vertical scan line with white pixels
  1948 				TInt bufLength = ByteWidth(height, aDispMode);
  1949 				aBuf.SetLength(bufLength);
  1950 				WhiteFill(ptr, bufLength, aDispMode);
  1951 				return;
  1952 				}
  1953 			}
  1954 		else
  1955 			{
  1956 			// no rasterizer - fill vertical scan line with white pixels
  1957 			TInt bufLength = ByteWidth(height, aDispMode);
  1958 			aBuf.SetLength(bufLength);
  1959 			WhiteFill(ptr, bufLength, aDispMode);
  1960 			return;
  1961 			}
  1962 		}
  1963 
  1964 	switch(aDispMode)
  1965 		{
  1966 		case EGray2:
  1967 			{
  1968 			TBool oddx=(aDitherOffset.iX&1);
  1969 			TBool oddy=(aDitherOffset.iY&1);
  1970 			height=Min(height,(TInt)((aBuf.MaxLength())<<3));
  1971 			aBuf.SetLength((height+7)>>3);
  1972 			TUint8 mask=1;
  1973 			for(TInt count=0;count<height;count++)
  1974 				{
  1975 				if (!mask)
  1976 					{
  1977 					mask=1;
  1978 					ptr++;
  1979 					*ptr = 0;
  1980 					}
  1981 				if (HashTo1bpp(GetGrayPixelEx(aX,slptr),oddx,oddy))
  1982 					*ptr|=mask;
  1983 				oddx^=1;
  1984 				mask<<=1;
  1985 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  1986 				}
  1987 			 break;
  1988 			}
  1989 		case EGray4:
  1990 			{
  1991 			height=Min(height,(TInt)((aBuf.MaxLength())<<2));
  1992 			aBuf.SetLength((height+3)>>2);
  1993 			TInt shift=0;
  1994 			TUint8 col=0;
  1995 			if (iHeader.iBitsPerPixel==4 && aDither)
  1996 				{
  1997 				const TInt hasharray[4]={0,3,2,1};
  1998 				TInt index=(aDitherOffset.iX&1)+((aDitherOffset.iY&1)<<1);
  1999 				for(TInt count=0;count<height;count++,shift+=2)
  2000 					{
  2001 					if (shift==8)
  2002 						{
  2003 						shift=0;
  2004 						ptr++;
  2005 						*ptr=0;
  2006 						}
  2007 					col = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
  2008 					TInt value = col / 5;
  2009 					col%=5;
  2010 					if (col>2) col--;
  2011 					if (hasharray[index]<TInt(col))
  2012 						value++;
  2013 					value<<=shift;
  2014 					*ptr|=value;
  2015 					index^=1;
  2016 					slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2017 					}
  2018 				}
  2019 			else
  2020 				{
  2021 				for(TInt count=0;count<height;count++,shift+=2)
  2022 					{
  2023 					if (shift==8)
  2024 						{
  2025 						shift=0;
  2026 						ptr++;
  2027 						*ptr=0;
  2028 						}
  2029 					col = TUint8(GetGrayPixelEx(aX,slptr) >> 6);
  2030 					col<<=shift;
  2031 					*ptr|=col;
  2032 					slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2033 					}
  2034 				}
  2035 			 break;
  2036 			}
  2037 		case EGray16:
  2038 			{
  2039 			height = Min(height,aBuf.MaxLength()<<1);
  2040 			aBuf.SetLength((height+1)>>1);
  2041 			TUint8* ptrLimit = ptr + aBuf.Length() - 1;
  2042 			while (ptr < ptrLimit)
  2043 				{
  2044 				*ptr = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
  2045 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2046 				*ptr++ |= GetGrayPixelEx(aX,slptr) & 0xf0;
  2047 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2048 				}
  2049 			// Fill last byte.
  2050 			// If height is odd, upper 4 bits are zeroed.
  2051 			*ptr = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
  2052 			if (!(height & 1))
  2053 				{
  2054 				// Only fill upper 4 bits of last byte if height is even. 
  2055 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2056 				*ptr++ = GetGrayPixelEx(aX,slptr) & 0xf0;
  2057 				}
  2058 			break;
  2059 			}
  2060 		case EColor16:
  2061 			{
  2062 			height=Min(height,aBuf.MaxLength()<<1);
  2063 			aBuf.SetLength((height+1)>>1);
  2064 			TUint8* ptrLimit = ptr + aBuf.Length() - 1;
  2065 
  2066 			while (ptr < ptrLimit)
  2067 				{
  2068 				*ptr = TUint8(GetRgbPixelEx(aX,slptr).Color16());
  2069 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2070 				*ptr++ |= GetRgbPixelEx(aX,slptr).Color16() << 4;
  2071 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2072 				}
  2073 			// Fill last byte.
  2074 			// If height is odd, upper 4 bits are zeroed.
  2075 			*ptr = TUint8(GetRgbPixelEx(aX,slptr).Color16());
  2076 			if (!(height & 1))
  2077 				{
  2078 				// Only fill upper 4 bits of last byte if height is even. 
  2079 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2080 				*ptr++ = GetRgbPixelEx(aX,slptr).Color16() << 4;
  2081 				}
  2082 			break;
  2083 			}
  2084 		case EGray256:
  2085 			{
  2086 			height = Min(height,aBuf.MaxLength());
  2087 			aBuf.SetLength(height);
  2088 			TUint8* ptrLimit = ptr + height;
  2089 			while (ptr < ptrLimit)
  2090 				{
  2091 				*ptr++ = GetGrayPixelEx(aX,slptr);
  2092 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2093 				}
  2094 			break;
  2095 			}
  2096 		case EColor256:
  2097 			{
  2098 			height = Min(height,aBuf.MaxLength());
  2099 			aBuf.SetLength(height);
  2100 			TUint8* ptrLimit = ptr + height;
  2101 
  2102 			while (ptr < ptrLimit)
  2103 				{
  2104 				*ptr++ = TUint8(GetRgbPixelEx(aX,slptr).Color256());
  2105 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2106 				}
  2107 			break;
  2108 			}
  2109 		case EColor4K:
  2110 			{
  2111 			height = Min(height,aBuf.MaxLength() >> 1);
  2112 			aBuf.SetLength(height << 1);
  2113 			TUint16* dwordPtr = (TUint16*)ptr;
  2114 			TUint16* ptrLimit = dwordPtr + height;
  2115 
  2116 			while (dwordPtr < ptrLimit)
  2117 				{
  2118 				*dwordPtr++ = TUint16(GetRgbPixelEx(aX,slptr)._Color4K());
  2119 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2120 				}
  2121 			break;
  2122 			}
  2123 		case EColor64K:
  2124 			{
  2125 			height = Min(height,aBuf.MaxLength() >> 1);
  2126 			aBuf.SetLength(height << 1);
  2127 			TUint16* dwordPtr = (TUint16*)ptr;
  2128 			TUint16* ptrLimit = dwordPtr + height;
  2129 
  2130 			while (dwordPtr < ptrLimit)
  2131 				{
  2132 				*dwordPtr++ = TUint16(GetRgbPixelEx(aX,slptr)._Color64K());
  2133 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2134 				}
  2135 			break;
  2136 			}
  2137 		case EColor16M:
  2138 			{
  2139 			height = Min(height,aBuf.MaxLength() / 3);
  2140 			aBuf.SetLength(height * 3);
  2141 			const TUint8* ptrLimit = ptr + (height * 3);
  2142 
  2143 			while (ptr < ptrLimit)
  2144 				{
  2145 				const TInt color16M = GetRgbPixelEx(aX,slptr)._Color16M();
  2146 				*ptr++ = TUint8(color16M);
  2147 				*ptr++ = TUint8(color16M >> 8);
  2148 				*ptr++ = TUint8(color16M >> 16);
  2149 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2150 				}
  2151 			break;
  2152 			}
  2153 		case ERgb:
  2154 		case EColor16MU:
  2155 		case EColor16MA:
  2156 		case EColor16MAP:
  2157 			{
  2158 			height = Min(height,aBuf.MaxLength() >> 2);
  2159 			aBuf.SetLength(height << 2);
  2160 			TUint32* pixelPtr = (TUint32*)ptr;
  2161 			TUint32* pixelPtrLimit = pixelPtr + height;
  2162 
  2163 			if (aDispMode == EColor16MAP && iSettings.CurrentDisplayMode() == EColor16MA)
  2164 				while (pixelPtr < pixelPtrLimit)
  2165 				{
  2166 				*pixelPtr++ = NonPMA2PMAPixel(*(slptr + aX));
  2167 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2168 				}
  2169 			else if (aDispMode == EColor16MAP && iSettings.CurrentDisplayMode() == EColor16MAP)
  2170 				while (pixelPtr < pixelPtrLimit)
  2171 				{
  2172 				*pixelPtr++ = *(slptr + aX);
  2173 				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2174 				}
  2175 			else if (aDispMode == EColor16MU)
  2176 				while (pixelPtr < pixelPtrLimit)
  2177 					{
  2178 					*pixelPtr++ = GetRgbPixelEx(aX, slptr).Internal() | 0xFF000000;
  2179 					slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2180 					}
  2181 			else
  2182 				while (pixelPtr < pixelPtrLimit)
  2183 					{
  2184 					*pixelPtr++ = GetRgbPixelEx(aX, slptr).Internal();
  2185 					slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
  2186 					}
  2187 			break;
  2188 			}
  2189 		default:
  2190 			aBuf.SetLength(0);
  2191 		}
  2192 	}
  2193 
  2194 EXPORT_C void CBitwiseBitmap::StretchScanLine(TDes8& aBuf,const TPoint& aPixel,TInt aClipStrchX,TInt aClipStrchLen,TInt aStretchLength,TInt aOrgX,TInt aOrgLen,const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase) const
  2195 	{
  2196 	TLineScanningPosition pos(aBase);
  2197 	StretchScanLine(aBuf,aPixel,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,pos);
  2198 	}
  2199 
  2200 EXPORT_C void CBitwiseBitmap::StretchScanLine(TDes8& aBuf,const TPoint& aPixel,TInt aClipStrchX,TInt aClipStrchLen,TInt aStretchLength,TInt aOrgX,TInt aOrgLen,const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
  2201 	{
  2202 	if (!iDataOffset)
  2203 		return;
  2204 	TInt x=aPixel.iX,y=aPixel.iY;
  2205 	if (x>=iHeader.iSizeInPixels.iWidth || x<-iHeader.iSizeInPixels.iWidth)
  2206 		x%=iHeader.iSizeInPixels.iWidth;
  2207 	if (y>=iHeader.iSizeInPixels.iHeight || y<-iHeader.iSizeInPixels.iHeight)
  2208 		y%=iHeader.iSizeInPixels.iHeight;
  2209 	if (x<0) x+=iHeader.iSizeInPixels.iWidth;
  2210 	if (y<0) y+=iHeader.iSizeInPixels.iHeight;
  2211 	if (aStretchLength<aOrgLen)
  2212 		DoCompressScanLine(aBuf,x,y,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,aLineScanningPosition);
  2213 	else
  2214 		DoStretchScanLine(aBuf,x,y,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,aLineScanningPosition);
  2215 	}
  2216 
  2217 EXPORT_C TUint32* CBitwiseBitmap::ScanLineAddress(TUint32* aBase,TUint aY) const
  2218 	{
  2219 	if (aY == 0 || iDataOffset == 0)
  2220 		return aBase;
  2221 
  2222 	if (aY >= TUint(iHeader.iSizeInPixels.iHeight))
  2223 		aY %= iHeader.iSizeInPixels.iHeight;
  2224 
  2225 	return aBase + (aY * (DataStride() >> 2));
  2226 	}
  2227 
  2228 TUint32* CBitwiseBitmap::DataAddress() const
  2229 	{
  2230 	if (iDataOffset==0) return(NULL);
  2231 
  2232 	if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid)   // RHardwareBitmap
  2233 		{
  2234 		RHardwareBitmap hwb(iDataOffset);	// iDataOffset = handle for hardware bitmap
  2235 		TAcceleratedBitmapInfo info;
  2236 		const TInt ret = hwb.GetInfo(info);
  2237 		return ret!=KErrNone ? NULL : (reinterpret_cast<TUint32*>(info.iAddress));
  2238 		}
  2239 
  2240 	if (iHeap == NULL)
  2241 		return(reinterpret_cast<TUint32*>((TUint8*)this+iDataOffset));
  2242 	return(reinterpret_cast<TUint32*>(iPile->ChunkBase()+iDataOffset));
  2243 	}
  2244 
  2245 EXPORT_C TInt CBitwiseBitmap::DataStride() const
  2246 	{
  2247 	return iByteWidth;
  2248 	}
  2249 
  2250 TUint32 CBitwiseBitmap::HashTo2bpp(TUint32 aGray256,TInt aDitherIndex) const
  2251 	{
  2252 	static const TUint hasharray[4]={0,3,2,1};
  2253 	TInt gray16 = aGray256 >> 4;
  2254 	TInt gray4 = gray16 + 1;
  2255 	gray4 += gray4 << 1;
  2256 	gray4 >>= 4;
  2257 	gray16 %= 5;
  2258 	if (gray16 > 2)
  2259 		gray16--;
  2260 	if (hasharray[aDitherIndex] < TUint(gray16))
  2261 		gray4++;
  2262 	return gray4;
  2263 	}
  2264 
  2265 TUint32 CBitwiseBitmap::HashTo1bpp(TUint32 aGray256,TBool aOddX,TBool aOddY) const
  2266 	{
  2267 	TUint32 aGray4 = aGray256 >> 6;
  2268 	switch(aGray4)
  2269 		{
  2270 		case 3:
  2271 			return 1;
  2272 		case 2:
  2273 			{
  2274 			if (aOddX && aOddY)
  2275 				return 0;
  2276 			else
  2277 				return 1;
  2278 			}
  2279 		case 1:
  2280 			{
  2281 			if ((aOddX && aOddY) || (!aOddX && !aOddY))
  2282 				return 1;
  2283 			}
  2284 			//coverity [fallthrough]
  2285 		default:
  2286 			return 0;
  2287 		}
  2288 	}
  2289 
  2290 /**
  2291 Tests whether or not the bitmap is monochrome.
  2292 Monochrome bitmaps have a display-mode of 1 bit-per-pixel.
  2293 Note: The method works for uncompressed bitmaps only.
  2294 @param aBase Bitmap's data base address
  2295 @return True if the bitmap is monochrome; false otherwise.
  2296 */
  2297 EXPORT_C TBool CBitwiseBitmap::IsMonochrome(TUint32* aBase) const
  2298 	{
  2299 	if (IsCompressed())
  2300 		{
  2301 		__ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
  2302 		return EFalse;  // Not currently supported for compressed bitmaps
  2303 		}
  2304 
  2305 	if (!iDataOffset)
  2306 		{
  2307 		return(EFalse);
  2308 		}
  2309 	TInt bitwidth=iHeader.iBitsPerPixel*iHeader.iSizeInPixels.iWidth;
  2310 	if(iHeader.iBitsPerPixel == 12)
  2311 		{//EColor4K mode - 1 pixel occupies 16 bits, most significant 4 bits are not used.
  2312 		bitwidth=16*iHeader.iSizeInPixels.iWidth;
  2313 		}
  2314 	TInt wordwidth=bitwidth>>5;
  2315 	TInt endshift=32-(bitwidth&0x1f);
  2316 	TInt endmask=0;
  2317 	if (endshift<32) endmask=0xffffffff>>endshift;
  2318 	TUint32* bitptr=aBase;
  2319 	//In a loop from first to last scanline:
  2320 	//Check each pixel - is it monochrome or not (pixel color must be BLACK or WHITE).
  2321 	//Get next scanline.
  2322 	TUint32* endbitptr=bitptr+wordwidth;
  2323 	for(TInt row=0;row<iHeader.iSizeInPixels.iHeight;row++)
  2324 		{
  2325 		if(iHeader.iBitsPerPixel == 24)
  2326 			{//1 word contains 1 pixel and 8 bits from the next pixel.
  2327 			for(TInt x=0;x<iHeader.iSizeInPixels.iWidth;x++)
  2328 				{
  2329 				TUint8* scanLine = reinterpret_cast <TUint8*> (bitptr) + x * 3;
  2330 				TUint color16M = *scanLine++;
  2331 				color16M |= (*scanLine++) << 8;
  2332 				color16M |= (*scanLine++) << 16;
  2333 				if (IsWordMonochrome(color16M)==EFalse)
  2334 					return(EFalse);
  2335 				}
  2336 			}
  2337 		else
  2338 			{
  2339 			TUint32* tmpbitptr=bitptr;
  2340 			while(tmpbitptr<endbitptr)
  2341 				if (IsWordMonochrome(*tmpbitptr++)==EFalse)
  2342 					return(EFalse);
  2343 			if (endmask)
  2344 				if (IsWordMonochrome(*endbitptr&endmask)==EFalse)
  2345 					return(EFalse);
  2346 			}
  2347 		bitptr+=wordwidth;
  2348 		endbitptr+=wordwidth;
  2349 		}
  2350 	return(ETrue);
  2351 	}
  2352 
  2353 TBool CBitwiseBitmap::IsWordMonochrome(TUint32 aWord) const
  2354 	{
  2355 	TDisplayMode displayMode = iSettings.CurrentDisplayMode();
  2356 	switch(displayMode)
  2357 		{
  2358 		case EGray2:
  2359 			return ETrue;
  2360 		case EGray4:
  2361 			{
  2362 			TUint32 lowerbits=aWord&0x55555555;
  2363 			TUint32 upperbits=(aWord>>1)&0x55555555;
  2364 			if (lowerbits^upperbits)
  2365 				return EFalse;
  2366 			return ETrue;
  2367 			}
  2368 		case EGray16:
  2369 		case EColor16:
  2370 			{
  2371 			if (aWord==0xffffffff || aWord==0)
  2372 				return ETrue;
  2373 			for(TInt count=0;count<8;count++)
  2374 				{
  2375 				TUint32 nibble=aWord&0xf;
  2376 				if ((nibble>0) && (nibble<0xf))
  2377 					return EFalse;
  2378 				aWord>>=4;
  2379 				}
  2380 			return ETrue;
  2381 			}
  2382 		case EGray256:
  2383 		case EColor256:
  2384 			{
  2385 			TUint8* bytePtr = (TUint8*)&aWord;
  2386 			TUint8* bytePtrLimit = bytePtr + 4;
  2387 			while (bytePtr < bytePtrLimit)
  2388 				{
  2389 				if (*bytePtr && (*bytePtr != 0xff))
  2390 					return EFalse;
  2391 				bytePtr++;
  2392 				}
  2393 			return ETrue;
  2394 			}
  2395 		case EColor4K:
  2396 			{
  2397 			aWord &= 0x0fff0fff;
  2398 			TUint16 color4K = (TUint16)aWord;
  2399 			if (color4K && (color4K != 0xfff))
  2400 				return EFalse;
  2401 			color4K = (TUint16)(aWord >> 16);
  2402 			if (color4K && (color4K != 0xfff))
  2403 				return EFalse;
  2404 			return ETrue;
  2405 			}
  2406 		case EColor64K:
  2407 			{
  2408 			TUint16 color64K = (TUint16)aWord;
  2409 			if (color64K && (color64K != 0xffff))
  2410 				return EFalse;
  2411 			color64K = (TUint16)(aWord >> 16);
  2412 			if (color64K && (color64K != 0xffff))
  2413 				return EFalse;
  2414 			return ETrue;
  2415 			}
  2416 		case EColor16M:
  2417 		case EColor16MU:
  2418 		case EColor16MA:
  2419 		case EColor16MAP:
  2420 			{
  2421 			aWord &= 0xffffff;
  2422 			if (aWord && (aWord != 0x00ffffff))
  2423 				return EFalse;
  2424 			return ETrue;
  2425 			}
  2426 		default:
  2427 			return EFalse;
  2428 		}
  2429 	}
  2430 
  2431 EXPORT_C TBool CBitwiseBitmap::IsLargeBitmap() const
  2432 	{
  2433 	if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid)
  2434 		return EFalse; // RHardwareBitmap
  2435 
  2436 	if (iHeap==NULL) return(EFalse); // rom bitmap
  2437 
  2438 	// Consider all RAM bitmaps large, so that legacy applications always
  2439 	// call LockHeap()/UnlockHeap() around DataAddress(), which allows
  2440 	// better handling of hardware acceleration caches, if present.
  2441 	// Note that, since the large bitmap threshold has always been in the
  2442 	// documentation, it is not guaranteed that legacy applications call
  2443 	// this function to determine whether a bitmap is large or not.
  2444 	return ETrue;
  2445 	}
  2446 
  2447 EXPORT_C TInt CBitwiseBitmap::HardwareBitmapHandle() const
  2448 	{
  2449 	if(iUid.iUid!=KCBitwiseBitmapHardwareUid.iUid)
  2450 		return 0;
  2451 	return iDataOffset; // Really the handle
  2452 	}
  2453 
  2454 /**
  2455 Set a flag to indicate that this bitmap has to be compressed in the FBServer background thread
  2456 @return KErrNone if possible to compress, KErrAlreadyExists if already compressed
  2457 */
  2458 EXPORT_C TInt CBitwiseBitmap::CheckBackgroundCompressData()
  2459 	{
  2460 	switch (iHeader.iBitsPerPixel)
  2461 		{
  2462 	case 1:
  2463 	case 2:
  2464 	case 4:
  2465 	case 8:
  2466 	case 12:
  2467 	case 16:
  2468 	case 24:
  2469 	case 32:
  2470 		break;
  2471 	default:
  2472 		return KErrNotSupported;
  2473 		}
  2474 	// Return if the bitmap is already compressed.
  2475 	if (iHeader.iCompression != ENoBitmapCompression)
  2476 		return KErrAlreadyExists;
  2477 
  2478 	// See if it's possible to allocate memory.
  2479 	if (iHeap == NULL || iPile == NULL)
  2480 		return KErrNoMemory;
  2481 
  2482 	return KErrNone;
  2483 	}
  2484 
  2485 
  2486 
  2487 /**
  2488 Compress a bitmap if possible.
  2489 If the bitmap is already compressed, or if compression yields no decrease in size, do nothing,
  2490 but return success (KErrNone).
  2491 @return KErrNone if successful, otherwise a system wide error code.
  2492 */
  2493 EXPORT_C TInt CBitwiseBitmap::CompressData()
  2494 	{
  2495 	switch (iHeader.iBitsPerPixel)
  2496 		{
  2497 	case 1:
  2498 	case 2:
  2499 	case 4:
  2500 	case 8:
  2501 	case 12:
  2502 	case 16:
  2503 	case 24:
  2504 	case 32:
  2505 		break;
  2506 	default:
  2507 		return KErrNone;
  2508 		}
  2509 	// Return if the bitmap is already compressed.
  2510 	if (iHeader.iCompression != ENoBitmapCompression)
  2511 		return KErrNone;
  2512 
  2513 	// Find out if compression is possible and return if not.
  2514 	TUint8* data = (TUint8*)DataAddress();
  2515 	TInt data_bytes = iHeader.iBitmapSize - iHeader.iStructSize;
  2516 
  2517 	//Update the padding bitmap data to speedup the RLE Compression
  2518 	UpdatePaddingData((TUint32*)data);
  2519 
  2520 	TInt compressed_data_bytes = (SizeOfDataCompressed((TUint8*)data,data_bytes) + 3) / 4 * 4;
  2521 
  2522 	if (!data || !data_bytes)
  2523 		return KErrNone;
  2524 
  2525 	//  	 if (compressed_data_bytes >= data_bytes)
  2526 	//  It now attempts to check whether compression is worth while.  (speed vs space saving)
  2527 	__ASSERT_DEBUG(KCompressionThreshold >=0 && KCompressionThreshold <= 256, ::Panic(EFbsInvalidCompressionThreshold));
  2528 	if (compressed_data_bytes >= (data_bytes * KCompressionThreshold) >> 8)
  2529 		return KErrNone;
  2530 
  2531 	// See if it's possible to allocate memory.
  2532 	if (iHeap == NULL || iPile == NULL)
  2533 		return KErrNoMemory;
  2534 
  2535 	// Create a buffer to receive the compressed data.
  2536 	TUint8* compressed_data = NULL;
  2537 	TInt allocSize = compressed_data_bytes;
  2538 	TBool bookMark = EFalse;
  2539 	if (allocSize > KCompressionBookMarkThreshold)
  2540 		{
  2541 		allocSize += sizeof(TCompressionBookMark) + 4;
  2542 		bookMark = ETrue;
  2543 		}
  2544 	compressed_data = iPile->Alloc(allocSize);
  2545 	if (!compressed_data)
  2546 		return KErrNoMemory;
  2547 	if (bookMark)
  2548 		{
  2549 		TCompressionBookMark emptyBookmark;
  2550 		*((TCompressionBookMark*)(compressed_data + compressed_data_bytes + 4)) = emptyBookmark;
  2551 		}
  2552 	iDataOffset = compressed_data - iPile->ChunkBase();
  2553 	iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + compressed_data_bytes;
  2554 	iHeader.iCompression = CompressionType(iHeader.iBitsPerPixel, iHeader.iColor);
  2555 
  2556 	// Compress the data into a stream over the new buffer.
  2557 	TPtr8 output_ptr(compressed_data,compressed_data_bytes);
  2558 	RDesWriteStream output_stream(output_ptr);
  2559 	// This function cannot leave - but trap it anyway till I am fully satisfied about that.
  2560 	TRAP_IGNORE(DoExternalizeDataCompressedL(output_stream,data,data_bytes));
  2561 	output_stream.Close();
  2562 
  2563 	iIsCompressedInRAM = ETrue;
  2564 	// Free the old data.
  2565 	iPile->Free(data);
  2566 
  2567 	return KErrNone;
  2568 	}
  2569 
  2570 /**
  2571 Compress a bitmap if possible.
  2572 If the bitmap is already compressed, or if compression yields no decrease in size, do nothing,
  2573 but return success (KErrNone).
  2574 @publishedAll
  2575 @param aScheme The type of bitmap file compression.
  2576 @return KErrNone if successful, otherwise a system wide error code.
  2577 */
  2578 EXPORT_C TInt CBitwiseBitmap::CompressData(TBitmapfileCompressionScheme aScheme)
  2579 	{
  2580 	TInt err=KErrNone;
  2581 	if (aScheme==ERLECompression)
  2582 		err=CompressData();
  2583 	else if (aScheme==EPaletteCompression)
  2584 		err=PaletteCompress();
  2585 	else if (aScheme==EPaletteCompressionWithRLEFallback)
  2586 		{
  2587 		err=PaletteCompress();
  2588 		if (err==KErrNotSupported)
  2589 			err=CompressData();
  2590 		}
  2591 
  2592 	return err;
  2593 	}
  2594 
  2595 EXPORT_C TBool CBitwiseBitmap::IsCompressedInRAM() const
  2596 	{
  2597 	return iIsCompressedInRAM;
  2598 	}
  2599 
  2600 /**
  2601 Check for a bitmap if it is compressed in some manner.
  2602 @return ETrue if successful Or EFalse if unsuccessful
  2603 @internalComponent
  2604 */
  2605 EXPORT_C TBool CBitwiseBitmap::IsCompressed() const
  2606 	{
  2607 	return ( iHeader.iCompression != ENoBitmapCompression );
  2608 	}
  2609 
  2610 EXPORT_C void CBitwiseBitmap::SetCompressionBookmark(TLineScanningPosition& aLineScanningPosition, TUint32* aBase, const CFbsBitmap* /*aFbsBitmap*/)
  2611 	{
  2612 	if (iPile == NULL) return; //Rom bitmap
  2613 	if (!iIsCompressedInRAM || (iHeader.iCompression == EGenericPaletteCompression))
  2614 		{
  2615 		return;
  2616 		}
  2617 
  2618 	TInt compressed_data_bytes=iHeader.iBitmapSize-sizeof(SEpocBitmapHeader);
  2619 	if (compressed_data_bytes>KCompressionBookMarkThreshold)
  2620 		{
  2621 		TUint8* compressed_data=(TUint8*) aBase;
  2622 		TInt alignedSize=(compressed_data_bytes+3)/4*4;
  2623 		compressed_data+=alignedSize+4;
  2624 		TCompressionBookMark* bookMark=(TCompressionBookMark*) (compressed_data);
  2625 		if (!bookMark->IsCheckSumOk())
  2626 			return;
  2627 		bookMark->iCursorPos=aLineScanningPosition.iCursorPos;
  2628 		bookMark->iSrcDataOffset=aLineScanningPosition.iSrcDataPtr-((TUint8*)aBase);
  2629 		bookMark->CalculateCheckSum();
  2630 		}
  2631 	}
  2632 /**
  2633 Optimises the bitmap data for Run Length Encoding by changing unused
  2634 pixel data.
  2635 This function calculates number of padding pixels per scanline and
  2636 replaces their color with the color of the scanline's final pixel.
  2637 */
  2638 void CBitwiseBitmap::UpdatePaddingData(TUint32* aData)
  2639 	{
  2640 	TInt stride=DataStride();
  2641 	//Do the process only for 8bpp and 16bpp.
  2642 	switch (iHeader.iBitsPerPixel)
  2643 		{
  2644 	case 8:
  2645 		{
  2646 		const TInt nPadding = stride - iHeader.iSizeInPixels.iWidth;
  2647 		if(nPadding!=1 && nPadding!=2 && nPadding!=3)
  2648 			return;
  2649 		TUint8* srcePtr = reinterpret_cast<TUint8*>(aData);
  2650 		//Find the last byte value in each scanline and assign in padding bytes
  2651 		TUint8* lastPixelPtr = srcePtr + iHeader.iSizeInPixels.iWidth - 1;
  2652 		for(TInt row=0; row<iHeader.iSizeInPixels.iHeight; row++)
  2653 			{
  2654 			TUint8 pixel = *lastPixelPtr;
  2655 			TUint8* padPtr = lastPixelPtr + 1;
  2656 			switch(nPadding)
  2657 				{
  2658 			case 3: *padPtr++ = pixel;
  2659 			case 2: *padPtr++ = pixel;
  2660 			case 1: *padPtr++ = pixel;
  2661 				}
  2662 			lastPixelPtr += stride;
  2663 			}
  2664 		break;
  2665 		}
  2666 	case 16:
  2667 		{
  2668 		TUint16* srcePtr = reinterpret_cast<TUint16*>(aData);
  2669 		stride>>=1;
  2670 		const TInt nPadding = stride - iHeader.iSizeInPixels.iWidth;
  2671 		if(nPadding!=1)
  2672 			return;
  2673 		//Find the last byte value in each scanline and assign in padding bytes
  2674 		TUint16* lastPixelPtr = srcePtr + iHeader.iSizeInPixels.iWidth - 1;
  2675 		for(TInt row=0; row<iHeader.iSizeInPixels.iHeight; row++)
  2676 			{
  2677 			TUint16 pixel = *lastPixelPtr;
  2678 			TUint16* padPtr = lastPixelPtr + 1;
  2679 			*padPtr++ = pixel;
  2680 			lastPixelPtr += stride;
  2681 			}
  2682 		break;
  2683 		}
  2684 	default:
  2685 		return;
  2686 		}
  2687 	}
  2688 
  2689 void CBitwiseBitmap::WhiteFill(TUint8* aData,TInt aDataSize,TDisplayMode aDispMode)
  2690 	{
  2691 	if(aData)
  2692 		{
  2693 		if (aDispMode != EColor4K)
  2694 			Mem::Fill(aData,aDataSize,0xff);
  2695 		else
  2696 			{
  2697 			TUint16* pixelPtr = (TUint16*)aData;
  2698 			TUint16* pixelPtrLimit = pixelPtr + (aDataSize / 2);
  2699 			while (pixelPtr < pixelPtrLimit)
  2700 				*pixelPtr++ = 0x0fff;
  2701 			}		
  2702 		}
  2703 	}
  2704 
  2705 TInt CBitwiseBitmap::ByteWidth(TInt aPixelWidth,TDisplayMode aDispMode)
  2706 	{
  2707 	TInt wordWidth = 0;
  2708 
  2709 	switch (aDispMode)
  2710 		{
  2711 	case EGray2:
  2712 		wordWidth = (aPixelWidth + 31) / 32;
  2713 		break;
  2714 	case EGray4:
  2715 		wordWidth = (aPixelWidth + 15) / 16;
  2716 		break;
  2717 	case EGray16:
  2718 	case EColor16:
  2719 		wordWidth = (aPixelWidth + 7) / 8;
  2720 		break;
  2721 	case EGray256:
  2722 	case EColor256:
  2723 		wordWidth = (aPixelWidth + 3) / 4;
  2724 		break;
  2725 	case EColor4K:
  2726 	case EColor64K:
  2727 		wordWidth = (aPixelWidth + 1) / 2;
  2728 		break;
  2729 	case EColor16M:
  2730 		wordWidth = (((aPixelWidth * 3) + 11) / 12) * 3;
  2731 		break;
  2732 	case EColor16MU:
  2733 	case ERgb:
  2734 	case EColor16MA:
  2735 	case EColor16MAP:
  2736 		wordWidth = aPixelWidth;
  2737 		break;
  2738 	default:
  2739 		::Panic(EFbsBitmapInvalidMode);
  2740 		}
  2741 
  2742 	return wordWidth * 4;
  2743 	}
  2744 
  2745 TInt CBitwiseBitmap::Bpp(TDisplayMode aDispMode)
  2746 	{
  2747 	switch (aDispMode)
  2748 		{
  2749 	case EGray2:
  2750 		return 1;
  2751 	case EGray4:
  2752 		return 2;
  2753 	case EGray16:
  2754 	case EColor16:
  2755 		return 4;
  2756 	case EGray256:
  2757 	case EColor256:
  2758 		return 8;
  2759 	case EColor4K:
  2760 		return 12;
  2761 	case EColor64K:
  2762 		return 16;
  2763 	case EColor16M:
  2764 		return 24;
  2765 	case EColor16MU:
  2766 	case EColor16MA:
  2767 	case EColor16MAP:
  2768 		return 32;
  2769 	default:
  2770 		::Panic(EFbsBitmapInvalidMode);
  2771 		}
  2772 
  2773 	return 0;
  2774 	}
  2775 
  2776 TInt CBitwiseBitmap::CompressedFormatInfo(TDisplayMode aDispMode, TInt& aBytesPerPack, TInt& aBytesPerCompressed)
  2777 	{
  2778 	switch (aDispMode)
  2779 		{
  2780 		case EGray2:
  2781 		case EGray4:
  2782 		case EGray16:
  2783 		case EColor16:
  2784 		case EGray256:
  2785 		case EColor256:
  2786 			aBytesPerPack = 1;
  2787 			aBytesPerCompressed = 1;
  2788 			break;
  2789 		case EColor4K:
  2790 		case EColor64K:
  2791 			aBytesPerPack = 2;
  2792 			aBytesPerCompressed = 2;
  2793 			break;
  2794 		case EColor16M:
  2795 			aBytesPerPack = 3;
  2796 			aBytesPerCompressed = 3;
  2797 			break;
  2798 		case EColor16MU:
  2799 			aBytesPerPack = 4;
  2800 			aBytesPerCompressed = 3;		 		  //when compressed, 16MU is stored as 16M 
  2801 			break;
  2802 		case EColor16MA:
  2803 		case EColor16MAP:
  2804 			aBytesPerPack = 4;
  2805 			aBytesPerCompressed = 4;
  2806 			break;
  2807 		default:
  2808 			__ASSERT_DEBUG(0, ::Panic(EFbsBitmapInvalidMode));
  2809 			return KErrNotSupported;
  2810 		}
  2811 
  2812 	return KErrNone;
  2813 	}
  2814 TInt CBitwiseBitmap::IsColor(TDisplayMode aDispMode)
  2815 	{
  2816 	switch (aDispMode)
  2817 		{
  2818 	case EGray2:
  2819 	case EGray4:
  2820 	case EGray16:
  2821 	case EGray256:
  2822 		return SEpocBitmapHeader::ENoColor;
  2823 	case EColor16:
  2824 	case EColor256:
  2825 	case EColor4K:
  2826 	case EColor64K:
  2827 	case EColor16M:
  2828 	case EColor16MU:
  2829 		return SEpocBitmapHeader::EColor;
  2830 	case EColor16MA:
  2831 		return SEpocBitmapHeader::EColorAlpha;
  2832 	case EColor16MAP:
  2833 		return SEpocBitmapHeader::EColorAlphaPM;
  2834 	default:
  2835 		::Panic(EFbsBitmapInvalidMode);
  2836 		}
  2837 
  2838 	return SEpocBitmapHeader::EColorUndefined;
  2839 	}
  2840 
  2841 TDisplayMode CBitwiseBitmap::DisplayMode(TInt aBpp, TInt aColor)
  2842 	{
  2843 	if (aColor)
  2844 		{
  2845 		switch (aBpp)
  2846 			{
  2847 		case 4:
  2848 			return EColor16;
  2849 		case 8:
  2850 			return EColor256;
  2851 		case 12:
  2852 			return EColor4K;
  2853 		case 16:
  2854 			return EColor64K;
  2855 		case 24:
  2856 			return EColor16M;
  2857 		case 32:
  2858 			if(aColor == SEpocBitmapHeader::EColor)
  2859 				return EColor16MU;
  2860 			else if(aColor == SEpocBitmapHeader::EColorAlphaPM)
  2861 				return EColor16MAP;
  2862 			else if(aColor == SEpocBitmapHeader::EColorAlpha)
  2863 				return EColor16MA;
  2864 			else
  2865 				return ENone;
  2866 		default:
  2867 			return ENone;
  2868 			}
  2869 		}
  2870 	else
  2871 		{
  2872 		switch (aBpp)
  2873 			{
  2874 		case 1:
  2875 			return EGray2;
  2876 		case 2:
  2877 			return EGray4;
  2878 		case 4:
  2879 			return EGray16;
  2880 		case 8:
  2881 			return EGray256;
  2882 		default:
  2883 			return ENone;
  2884 			}
  2885 		}
  2886 	}
  2887 
  2888 TBitmapfileCompression CBitwiseBitmap::CompressionType(TInt aBpp, TInt aColor)
  2889 	{
  2890 	switch (aBpp)
  2891 		{
  2892 	case 1:
  2893 	case 2:
  2894 	case 4:
  2895 	case 8:
  2896 		return EByteRLECompression;
  2897 	case 12:
  2898 		return ETwelveBitRLECompression;
  2899 	case 16:
  2900 		return ESixteenBitRLECompression;
  2901 	case 24:
  2902 		return ETwentyFourBitRLECompression;
  2903 	case 32:
  2904 		__ASSERT_DEBUG((aColor==SEpocBitmapHeader::EColor) ||
  2905 				(aColor==SEpocBitmapHeader::EColorAlpha) ||
  2906 				aColor==SEpocBitmapHeader::EColorAlphaPM,
  2907 				::Panic(EFbsBitmapInvalidCompression));
  2908 		if(aColor == SEpocBitmapHeader::EColor)
  2909 			{
  2910 			return EThirtyTwoUBitRLECompression;
  2911 			}
  2912 		else
  2913 			{
  2914 			return EThirtyTwoABitRLECompression;
  2915 			}
  2916 	default:
  2917 		return ENoBitmapCompression;
  2918 		}
  2919 	}
  2920 
  2921 /**
  2922 @internalComponent
  2923 @return The display mode used to create the bitmap.
  2924 */
  2925 TDisplayMode CBitwiseBitmap::InitialDisplayMode() const
  2926 	{
  2927 	return iSettings.InitialDisplayMode();
  2928 	}
  2929 
  2930 /**
  2931 The method changes current display mode of the bitmap.
  2932 Requested display mode can't be greater (bpp value) than the initial display mode.
  2933 CBitwiseBitmap instances are shared between the client and server side and
  2934 SetDisplayMode() can be called only from the client side, because its functionality depends
  2935 on the RFbsSession instance.
  2936 The method can't leave because of out of memory condition or something else - no
  2937 additional memory is allocated or "L" methods called.
  2938 The bitmap content is preserved when converting it to the requested display mode,
  2939 but there may be some loss of a quality.
  2940 @internalComponent
  2941 @param aDisplayMode Requested display mode.
  2942 @param aDataAddress Bitmap data address.
  2943 @return KErrArgument If the requested mode is invalid, or greater (bpp value) than the
  2944 initial display mode.
  2945 @return KErrNotSupported  If the bitmap is compressed, or it is a ROM bitmap,
  2946 an extended bitmap or a hardware bitmap.
  2947 @return KErrNone If the method call is successfull.
  2948 */
  2949 TInt CBitwiseBitmap::SetDisplayMode(TDisplayMode aDisplayMode, TUint32* aDataAddress)
  2950 	{
  2951 	TDisplayMode curDisplayMode = iSettings.CurrentDisplayMode();
  2952 	//If requested mode is the same as current mode - do nothing.
  2953 	if(curDisplayMode == aDisplayMode)
  2954 		{
  2955 		return KErrNone;
  2956 		}
  2957 	//Argument and bitmap state check.
  2958 	TInt err = DisplayModeArgCheck(aDisplayMode, aDataAddress);
  2959 	if(err != KErrNone)
  2960 		{
  2961 		return err;
  2962 		}
  2963 	//data pointers and scan line width calculation.
  2964 	TInt scanLineWidthNew = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iWidth, aDisplayMode);
  2965 	TInt scanLineWidthInitial = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iWidth, iSettings.InitialDisplayMode());
  2966 	TInt bmpSizeInitial = scanLineWidthInitial * iHeader.iSizeInPixels.iHeight;
  2967 	TUint8* baseAddr = reinterpret_cast <TUint8*> (aDataAddress);
  2968 	TUint8* dataAddrNew = baseAddr;
  2969 	TInt yStart = 0;
  2970 	TInt yInc = 1;
  2971 	TInt yEnd = iHeader.iSizeInPixels.iHeight;
  2972 	//If requested display mode has more bits per pixel than current display mode - we have
  2973 	//to start copying operation from the end of the bitmap, otherwise we will overwrite the
  2974 	//bitmap data.
  2975 	if(aDisplayMode > curDisplayMode)
  2976 		{
  2977 		dataAddrNew += bmpSizeInitial - scanLineWidthNew;
  2978 		scanLineWidthNew = -scanLineWidthNew;
  2979 		yStart = yEnd - 1;
  2980 		yInc = -1;
  2981 		yEnd = -1;
  2982 		}
  2983 	//Change the display mode
  2984 	ChangeDisplayMode(aDisplayMode, scanLineWidthNew, dataAddrNew, aDataAddress, yStart, yInc, yEnd);
  2985 	//Move the data to the aDataAddress.
  2986 	if(aDisplayMode > curDisplayMode)
  2987 		{
  2988 		TInt bmpSizeNew = -scanLineWidthNew * iHeader.iSizeInPixels.iHeight;
  2989 		Mem::Move(baseAddr, baseAddr + bmpSizeInitial - bmpSizeNew, bmpSizeNew);
  2990 		}
  2991 	//Update the bitmap properties
  2992 	UpdateBitmapProperties(aDisplayMode);
  2993 	return KErrNone;
  2994 	}
  2995 
  2996 /**
  2997 The method is caled from CBitwiseBitmap::SetDisplayMode() and
  2998 checks the aDisplayMode argument and bitmap internal state.
  2999 Requested display mode can't be greater (bpp value) than the initial display mode.
  3000 Note: The method must be called only from CBitwiseBitmap::SetDisplayMode method.
  3001 @internalComponent
  3002 @param aDisplayMode Requested display mode.
  3003 @param aDataAddress Bitmap data address.
  3004 @return KErrArgument If the requested mode is invalid, or greater (bpp value)
  3005 than the initial mode.
  3006 @return KErrNotSupported If the bitmap is compressed, or it is a ROM bitmap,
  3007 an extended bitmap or a hardware bitmap.
  3008 @return KErrNone If the method call is successfull.
  3009 @see CBitwiseBitmap::SetDisplayMode.
  3010 */
  3011 TInt CBitwiseBitmap::DisplayModeArgCheck(TDisplayMode aDisplayMode, TUint32* aDataAddress) const
  3012 	{
  3013 	if(!aDataAddress || iHeader.iSizeInPixels.iWidth == 0 || iHeader.iSizeInPixels.iHeight == 0)
  3014 		{
  3015 		return KErrGeneral;
  3016 		}
  3017 	TBool romAddr = EFalse;
  3018 	User::IsRomAddress(romAddr, aDataAddress);
  3019 	if(romAddr ||									//ROM bitmap
  3020 	   (iUid.iUid != KCBitwiseBitmapUid.iUid) ||	//RHardwareBitmap or extended bitmap
  3021 	   IsCompressed()								//Compressed
  3022 	  )
  3023 		{
  3024 		return KErrNotSupported;
  3025 		}
  3026 	if(aDisplayMode == ENone || aDisplayMode == ERgb)
  3027 		{
  3028 		return KErrArgument;
  3029 		}
  3030 	if (iSettings.InitialDisplayMode()==EColor16 && aDisplayMode==EGray256)
  3031 		{
  3032 		return KErrArgument;
  3033 		}
  3034 	// The order of the display mode in the TDisplayMode
  3035 	// ENone,EGray2,EGray4,EGray16,EGray256,EColor16,EColor256,EColor64K,EColor16M,ERgb,EColor4K,EColor16MU
  3036 
  3037 	//special case where initial mode is EColor4K & to be set to EColor64K & EColor16M which has lower enum
  3038 	if (iSettings.InitialDisplayMode()==EColor4K )
  3039 		{
  3040 		if (aDisplayMode==EColor64K || aDisplayMode==EColor16M)
  3041 			return KErrArgument;
  3042 		}
  3043 
  3044 	if(aDisplayMode == EColor16MAP)
  3045 		{
  3046 		TDisplayMode mode = iSettings.InitialDisplayMode();
  3047 		if((mode == EColor16MA)||(mode == EColor16MU)||(mode == EColor16MAP))
  3048 			{
  3049 			return KErrNone;
  3050 			}
  3051 		else{
  3052 			return KErrArgument;
  3053 			}
  3054 		}
  3055 	if(iSettings.InitialDisplayMode() == EColor16MAP)
  3056 		{
  3057 		return KErrNone;
  3058 		}
  3059 	if(aDisplayMode > iSettings.InitialDisplayMode())
  3060 		{
  3061 		if (iSettings.InitialDisplayMode()>=EColor64K && aDisplayMode == EColor4K)
  3062 			{
  3063 			return KErrNone;
  3064 			}
  3065 	        if (iSettings.InitialDisplayMode()==EColor16MU &&
  3066 	        	(Bpp(aDisplayMode) == 32))
  3067 			{
  3068 			return KErrNone;
  3069 			}
  3070 		return KErrArgument;
  3071 		}
  3072 
  3073 	return KErrNone;
  3074 	}
  3075 
  3076 /**
  3077 The method changes current display mode of the bitmap converting bitmap scan lines
  3078 color and writting the resulting scan line to the same memory occupied by the bitmap.
  3079 No additional memory is allocated.
  3080 Note: The method must be called only from CBitwiseBitmap::SetDisplayMode method.
  3081 @internalComponent
  3082 @param aNewDisplayMode Requested display mode.
  3083 @param aScanLineWidthNew Scan line width - with the new display mode. It could be negative
  3084 if the new display mode is with less bits per pixel than the existing display mode.
  3085 @param aDataAddrNew New bitmap data - Points to the place where the copying has to start to.
  3086 @param aDataAddress Bitmap data address.
  3087 @param aYStart First scan line number.
  3088 @param aYInc Scan line increment value.
  3089 @param aYEnd Last scan line number.
  3090 @see CBitwiseBitmap::SetDisplayMode.
  3091 */
  3092 void CBitwiseBitmap::ChangeDisplayMode( TDisplayMode aNewDisplayMode,
  3093 										TInt aScanLineWidthNew,
  3094 										TUint8* aDataAddrNew,
  3095 										TUint32* aDataAddress,
  3096 										TInt aYStart,
  3097 										TInt aYInc,
  3098 										TInt aYEnd)
  3099 	{
  3100 	const TInt KScanLineBufSizeInPixels = 256;//temporary scan line buffer size - in pixels
  3101 	const TInt KRgbBytes = 4;
  3102 	const TInt KScanLineBufSizeInBytes = KScanLineBufSizeInPixels * KRgbBytes;
  3103 	TUint8 scanLineData[KScanLineBufSizeInBytes];
  3104 	static const TInt KScanLinePixels[] =  //The rounded number of pixels - the closest number that
  3105 		{							//could fill scanLineData buffer - depending on current display mode
  3106 		0,												//ENone - INVALID mode
  3107 		KScanLineBufSizeInBytes * 8,					//EGray2
  3108 		KScanLineBufSizeInBytes * 4,					//EGray4
  3109 		KScanLineBufSizeInBytes * 2,					//EGray16
  3110 		KScanLineBufSizeInBytes * 1,					//EGray256
  3111 		KScanLineBufSizeInBytes * 2,					//EColor16
  3112 		KScanLineBufSizeInBytes * 1,					//EColor256
  3113 		KScanLineBufSizeInPixels * KRgbBytes / 2,		//EColor64K
  3114 		KScanLineBufSizeInPixels,						//EColor16M
  3115 		0,												//ERgb - INVALID mode
  3116 		KScanLineBufSizeInPixels * KRgbBytes / 2,		//EColor4K - the same as EColor64K
  3117 		KScanLineBufSizeInPixels * KRgbBytes / 4,		//EColor16MU
  3118 		KScanLineBufSizeInPixels * KRgbBytes / 4,		//EColor16MA
  3119 		KScanLineBufSizeInPixels * KRgbBytes / 4		//EColor16MAP
  3120 		};
  3121 	__ASSERT_DEBUG(aNewDisplayMode < TInt(sizeof(KScanLinePixels) / sizeof(KScanLinePixels[0])), ::Panic(EFbsBitmapInvalidMode3));
  3122 	//
  3123 	TPtr8 ptr(scanLineData, sizeof(scanLineData), sizeof(scanLineData));
  3124 	TDes8& scanLineDes = ptr;
  3125 	TLineScanningPosition lineScanningPosition(aDataAddress);
  3126 	TPoint startPixel(0, 0);
  3127 	TPoint ditherOffset(0, 0);
  3128 	//For each line:
  3129 	//1. Get a scan line in requested display mode
  3130 	//2. Copy the scan line to the destination buffer, pointed by dataAddrNew
  3131 	TUint8* dataAddrNew = aDataAddrNew;
  3132 	for(TInt i=aYStart;i!=aYEnd;i+=aYInc)
  3133 		{
  3134 		startPixel.iX = 0;
  3135 		startPixel.iY = i;
  3136 		TUint8* scanLineDataAddr = dataAddrNew;
  3137 		TInt scanLinePixelsLeft = iHeader.iSizeInPixels.iWidth;
  3138 		while(scanLinePixelsLeft > 0)
  3139 			{
  3140 			TInt pixelsCnt = KScanLinePixels[aNewDisplayMode];	//how many pixels we can get at a time - the maximum
  3141 			TInt bytesCnt = KScanLineBufSizeInBytes;			//how many bytes the pixels are - the maximum
  3142 			if(pixelsCnt > scanLinePixelsLeft)	//in that case the "while" loop will be executed for the last time
  3143 				{
  3144 				pixelsCnt = scanLinePixelsLeft;
  3145 				bytesCnt = CBitwiseBitmap::ByteWidth(pixelsCnt, aNewDisplayMode);
  3146 				}
  3147 			__ASSERT_DEBUG(pixelsCnt > 0, ::Panic(EFbsBitmapInvalidMode2));//I want to be sure - if someone adds an additional display mode - ChangeDisplayMode() source has been updated too!
  3148 			GetScanLine(scanLineDes, startPixel, pixelsCnt, EFalse,	  //Get the scan line data
  3149 						ditherOffset, aNewDisplayMode, aDataAddress, lineScanningPosition);
  3150 			Mem::Copy(scanLineDataAddr, scanLineData, bytesCnt);//copy the data to its new address
  3151 			scanLineDataAddr += bytesCnt;//increment the address
  3152 			scanLinePixelsLeft -= pixelsCnt;//decrement the count of pixels left
  3153 			startPixel.iX += pixelsCnt;//increment the X coordinate
  3154 			}//end of - while(scanLineLengthLeft > 0)
  3155 		dataAddrNew += aScanLineWidthNew;
  3156 		}//end of - for(TInt i=aYStart;i!=aYEnd;i+=aYInc)
  3157 	}
  3158 
  3159 /**
  3160 The method updates CBitwiseBitmap data members regarding to the new display mode.
  3161 Note: The method must be called only from CBitwiseBitmap::SetDisplayMode method.
  3162 @internalComponent
  3163 @param aNewDisplayMode The new display mode.
  3164 @see CBitwiseBitmap::SetDisplayMode.
  3165 */
  3166 void CBitwiseBitmap::UpdateBitmapProperties(TDisplayMode aNewDisplayMode)
  3167 	{
  3168 	iSettings.SetCurrentDisplayMode(aNewDisplayMode);
  3169 	iByteWidth = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iWidth, aNewDisplayMode);
  3170 	iHeader.iBitsPerPixel = CBitwiseBitmap::Bpp(aNewDisplayMode);
  3171 	iHeader.iColor = CBitwiseBitmap::IsColor(aNewDisplayMode);
  3172 	}
  3173 
  3174 /**
  3175 The method swaps the bitmap width and height.
  3176 For example: if the bitmap size is (40, 20), the new bitmap size will be (20, 40).
  3177 Bitmap content is not preserved.
  3178 @internalComponent
  3179 @param aDataAddress Bitmap data address.
  3180 @return KErrNone The call was successfull.
  3181 @return KErrAccessDenied ROM bitmap size can't be swapped.
  3182 @return KErrNotSupported Hardware or extended bitmap size can't be swapped.
  3183 */
  3184 TInt CBitwiseBitmap::SwapWidthAndHeight(TUint32* aDataAddress)
  3185 	{
  3186 	if (iUid.iUid != KCBitwiseBitmapUid.iUid)	// RHardwareBitmap or extended bitmap
  3187 		{
  3188 		return KErrNotSupported;
  3189 		}
  3190 
  3191 	TBool romAddr = EFalse;
  3192 	User::IsRomAddress(romAddr, aDataAddress);
  3193 	if (romAddr)								//ROM bitmap
  3194 		{
  3195 		return KErrAccessDenied;
  3196 		}
  3197 
  3198     //Check the new bitmap size - it should not exeed the size of the allocated memory
  3199     TInt newWidthInBytes = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iHeight, iSettings.CurrentDisplayMode());
  3200 	TInt64 hugeDataSize = TInt64(iHeader.iSizeInPixels.iWidth) * TInt64(newWidthInBytes);
  3201     __ASSERT_ALWAYS(I64HIGH(hugeDataSize) == 0 &&
  3202                     I64LOW(hugeDataSize) <= TUint(iHeader.iBitmapSize - iHeader.iStructSize),
  3203                     ::Panic(EFbsBitmapSwappingImpossible));
  3204 
  3205 	//Initialize the data members with the new values
  3206 	iByteWidth = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iHeight, iSettings.CurrentDisplayMode());
  3207 	TInt temp = iHeader.iSizeInPixels.iWidth;
  3208 	iHeader.iSizeInPixels.iWidth = iHeader.iSizeInPixels.iHeight;
  3209 	iHeader.iSizeInPixels.iHeight = temp;
  3210 	temp = iHeader.iSizeInTwips.iWidth;
  3211 	iHeader.iSizeInTwips.iWidth = iHeader.iSizeInTwips.iHeight;
  3212 	iHeader.iSizeInTwips.iHeight = temp;
  3213 	return KErrNone;
  3214 	}
  3215 
  3216 /**
  3217 Compile time check is performed on the class size - the class size must be
  3218 the same as the size of TDisplayMode type. If the class size is not the same
  3219 as  TDisplayMode type size - BC will be broken.
  3220 Note: CBitwiseBitmap::iSettings data member must be aligned on 16 bits boundary
  3221 because CBitwiseBitmap instances can be a part of the ROM image.
  3222 @internalComponent
  3223 @param aDisplayMode The display mode.
  3224 */
  3225 CBitwiseBitmap::TSettings::TSettings(TDisplayMode aDisplayMode):
  3226 	iData(0)
  3227 	{
  3228 	//"CBitwiseBitmap::iSettings" data mamber - bit format:
  3229 	// MSB                                              LSB
  3230 	// 16         			:           8             :            8
  3231 	// Flags                  Initial display mode      Current display mode
  3232 	//
  3233 	//CBitwiseBitmap - TSettings member has been put in place of previous iDispMode
  3234 	//class member. So, TSettings data member has to occupy the same space as
  3235 	//not existing anymore iDispMode member.
  3236 	COMPILE_TIME_ASSERT(sizeof(TSettings) == sizeof(TDisplayMode));
  3237 	//We can't have TDisplayMode enum value greater than 255 because we encode it
  3238 	//int 8 bits of iData data member.
  3239 	COMPILE_TIME_ASSERT(EColorLast < 256);
  3240 	SetDisplayModes(aDisplayMode);
  3241 	}
  3242 
  3243 /**
  3244 The method initializes both - current display mode and initial display mode parts of iData
  3245 with aDisplayMode parameter.
  3246 @internalComponent
  3247 @param aDisplayMode The display mode used for current display mode and initial display mode
  3248 parts of iData initialization
  3249 */
  3250 void CBitwiseBitmap::TSettings::SetDisplayModes(TDisplayMode aDisplayMode)
  3251 	{
  3252 	iData &= 0xFFFF0000;
  3253 	iData |= TUint16(aDisplayMode << 8);
  3254 	iData |= TUint8(aDisplayMode);
  3255 	}
  3256 
  3257 /**
  3258 The method initializes current display mode part of iData with aDisplayMode parameter.
  3259 @internalComponent
  3260 @param aDisplayMode The display mode used for current display mode part of iData initialization.
  3261 */
  3262 void CBitwiseBitmap::TSettings::SetCurrentDisplayMode(TDisplayMode aDisplayMode)
  3263 	{
  3264 	iData &= 0xFFFFFF00;
  3265 	iData |= TUint8(aDisplayMode);
  3266 	}
  3267 
  3268 /**
  3269 The method returns current display mode.
  3270 @internalComponent
  3271 Note: Current display mode can never be greater (bpp value) than initial display mode.
  3272 @return Current display mode.
  3273 */
  3274 TDisplayMode CBitwiseBitmap::TSettings::CurrentDisplayMode() const
  3275 	{
  3276 	return TDisplayMode(iData & 0x000000FF);
  3277 	}
  3278 
  3279 /**
  3280 The method returns initial display mode.
  3281 @internalComponent
  3282 @return The initial display mode.
  3283 */
  3284 TDisplayMode CBitwiseBitmap::TSettings::InitialDisplayMode() const
  3285 	{
  3286 	return TDisplayMode((iData & 0x0000FF00) >> 8);
  3287 	}
  3288 
  3289 /**
  3290 The method adjusts specified X coordinate if it is negative or outside the bitmap.
  3291 @internalComponent
  3292 @param  aX - a reference to x coordinate - the value might be changed after the method call.
  3293 */
  3294 void CBitwiseBitmap::AdjustXCoord(TInt& aX) const
  3295 	{
  3296 	if (aX>=iHeader.iSizeInPixels.iWidth || aX<-iHeader.iSizeInPixels.iWidth)
  3297 		aX%=iHeader.iSizeInPixels.iWidth;
  3298 	if (aX<0)
  3299 		aX+=iHeader.iSizeInPixels.iWidth;
  3300 	}
  3301 
  3302 /**
  3303 If the bitmap is compressed in RAM, the method will find its compresssion bookmark,
  3304 which is located at the end of the bitmap data and will reinitialize aLineScanPos
  3305 parameter.
  3306 @internalComponent
  3307 @param aLineScanPos Line scaning position. It is used by scan line decompression methods.
  3308 @param aComprBookMark If the bitmap is compressed in RAM, aComprBookMark will be initialized
  3309 to point to its compression bookmark data. The compression bookmark data will be used for
  3310 aLineScanPos initialization.
  3311 @param  aBase It points to the beginning of the bitmap data.
  3312 */
  3313 void CBitwiseBitmap::GetLineScanPos(TLineScanningPosition& aLineScanPos,
  3314 									const TCompressionBookMark*& aComprBookMark,
  3315 									const TUint8* aBase) const
  3316 	{
  3317 	if (iIsCompressedInRAM && (iHeader.iCompression != EGenericPaletteCompression) && (iHeap != NULL))
  3318 		{
  3319 		TInt compressed_data_bytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
  3320 		if(compressed_data_bytes > KCompressionBookMarkThreshold)
  3321 			{
  3322 			if(aBase)
  3323 				{
  3324 				TInt alignedSize = (compressed_data_bytes + 3) / 4 * 4;
  3325 				const TUint8* data = aBase + alignedSize + 4;
  3326 				aComprBookMark = reinterpret_cast <const TCompressionBookMark*> (data);
  3327 				if (aComprBookMark->IsCheckSumOk())
  3328 					{
  3329 					aLineScanPos.iSrcDataPtr = const_cast <TUint8*> (aBase) + aComprBookMark->iSrcDataOffset;
  3330 					aLineScanPos.iCursorPos = aComprBookMark->iCursorPos;
  3331 					}
  3332 				}
  3333 			}
  3334 		}
  3335 	}
  3336 
  3337 /**
  3338 If the bitmap is compressed in RAM, the method will update its compresssion bookmark data,
  3339 which is located at the end of the bitmap data.
  3340 @internalComponent
  3341 @param aLineScanPos Line scaning position.
  3342 @param aComprBookMark If the bitmap is compressed in RAM, aComprBookMark points to its
  3343 compression bookmark data.
  3344 @param  aBase It points to the beginning of the bitmap data.
  3345 */
  3346 void CBitwiseBitmap::UpdateBookMark(const TLineScanningPosition& aLineScanPos,
  3347 									TCompressionBookMark* aComprBookMark,
  3348 									const TUint8* aBase) const
  3349 	{
  3350 	if (aComprBookMark)
  3351 		{
  3352 		if (aComprBookMark->IsCheckSumOk())
  3353 			{
  3354 			aComprBookMark->iSrcDataOffset=aLineScanPos.iSrcDataPtr-aBase;
  3355 			aComprBookMark->iCursorPos=aLineScanPos.iCursorPos;
  3356 			aComprBookMark->CalculateCheckSum();
  3357 			}
  3358 		}
  3359 	}
  3360 
  3361 /**
  3362 The header is exposed by CFbsBitmap so this doesn't break encapsulation.
  3363 Specifically added to allow CBitmapObject to see compression information.
  3364 @return Address of iHeader.
  3365 */
  3366 EXPORT_C SEpocBitmapHeader CBitwiseBitmap::Header() const
  3367 	{
  3368 	return iHeader ;
  3369 	}