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.
<
sl@0
     1
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <f32file.h>
sl@0
    17
#include <fbs.h>
sl@0
    18
#include <bitmap.h>
sl@0
    19
#include <graphicsaccelerator.h>
sl@0
    20
#include <graphics/lookuptable.h>
sl@0
    21
#include <graphics/blendingalgorithms.h>
sl@0
    22
#include <graphics/bitmapuid.h>
sl@0
    23
#include "UTILS.H"
sl@0
    24
#include <s32mem.h>
sl@0
    25
#include "ShiftedFileStore.h"
sl@0
    26
#include "CompileAssert.h"
sl@0
    27
#include "CompressionBookmark.h"
sl@0
    28
#include "BitmapCompr.h"
sl@0
    29
#include "palette.h"
sl@0
    30
#include "fbsrasterizer.h"
sl@0
    31
#include "bitmap.inl"
sl@0
    32
#include "BitwiseBitmap.inl"
sl@0
    33
#include "bitmapconst.h"
sl@0
    34
sl@0
    35
#ifdef __ARMCC__
sl@0
    36
#pragma arm
sl@0
    37
#pragma O3
sl@0
    38
#pragma Otime
sl@0
    39
#endif
sl@0
    40
sl@0
    41
const TInt KMaxPixelSize = KMaxTInt / 4; // Maximum pixel size to avoid some overflow problems
sl@0
    42
const TUint KMaxByteSize = TUint(KMaxTInt / 2); // Maximum byte size to avoid other overflow problems
sl@0
    43
enum
sl@0
    44
    {
sl@0
    45
    EFirstTime = 65536
sl@0
    46
    };
sl@0
    47
GLREF_C void Panic(TFbsPanic aPanic);
sl@0
    48
sl@0
    49
#define COLOR_VALUE(ScanLinePtr, XPos) (*((ScanLinePtr) + ((XPos) >> 5)) & ( 1 << ((XPos) & 0x1F)))
sl@0
    50
sl@0
    51
EXPORT_C void CBitwiseBitmap::operator delete(TAny *aThis)
sl@0
    52
	{
sl@0
    53
	if (((CBitwiseBitmap*)aThis)->iHeap)
sl@0
    54
		((CBitwiseBitmap*)aThis)->iHeap->Free(aThis);
sl@0
    55
	}
sl@0
    56
sl@0
    57
EXPORT_C CBitwiseBitmap::CBitwiseBitmap(RHeap* aHeap,CChunkPile* aPile):
sl@0
    58
	iUid(KCBitwiseBitmapUid),
sl@0
    59
	iSettings(ENone),
sl@0
    60
	iHeap(aHeap),
sl@0
    61
	iPile(aPile),
sl@0
    62
	iByteWidth(0),
sl@0
    63
	iDataOffset(0),
sl@0
    64
	iIsCompressedInRAM(EFalse)
sl@0
    65
	{
sl@0
    66
	//CBitwiseBitmap size can't be changed! If the bitmap is ROM based,
sl@0
    67
	//then CBitwiseBitmap object is not created, but CBitwiseBitmap pointer is
sl@0
    68
	//used to access ROM based bitmap data.
sl@0
    69
	//The following line is a part of CFbsBitmap::DoLoad(...) source code:
sl@0
    70
	//iRomPointer=(CBitwiseBitmap*)(((TUint8*)rompointer)+offset);
sl@0
    71
	//We have to preserve data compatibility with already existing ROM bitmaps.
sl@0
    72
	enum
sl@0
    73
		{
sl@0
    74
		KCBitwiseBitmapSize = 72
sl@0
    75
		};
sl@0
    76
	COMPILE_TIME_ASSERT(sizeof(CBitwiseBitmap) == KCBitwiseBitmapSize);
sl@0
    77
#ifdef SYMBIAN_DEBUG_FBS_LOCKHEAP
sl@0
    78
	Extra()->iLockCount = 0;
sl@0
    79
	Extra()->iThreadId = TThreadId(KNullThreadId);
sl@0
    80
#endif
sl@0
    81
	Extra()->iTouchCount = 0;
sl@0
    82
	Extra()->iSerialNumber = 0;
sl@0
    83
	}
sl@0
    84
sl@0
    85
EXPORT_C CBitwiseBitmap::~CBitwiseBitmap()
sl@0
    86
	{
sl@0
    87
	Reset();
sl@0
    88
	}
sl@0
    89
sl@0
    90
EXPORT_C void CBitwiseBitmap::Reset()
sl@0
    91
	{
sl@0
    92
	if (iDataOffset)
sl@0
    93
		{
sl@0
    94
		if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid)
sl@0
    95
			{
sl@0
    96
			RHardwareBitmap hwb(iDataOffset);	// iDataOffset = handle for hardware bitmap
sl@0
    97
			hwb.Destroy();
sl@0
    98
			}
sl@0
    99
		else
sl@0
   100
			if (iPile) iPile->Free(DataAddress());
sl@0
   101
		}
sl@0
   102
	iUid.iUid = KCBitwiseBitmapUid.iUid;
sl@0
   103
	iDataOffset=0;
sl@0
   104
	iSettings.SetDisplayModes(ENone);
sl@0
   105
	iByteWidth=0;
sl@0
   106
	iHeader=SEpocBitmapHeader();
sl@0
   107
	iIsCompressedInRAM=EFalse;
sl@0
   108
	}
sl@0
   109
sl@0
   110
EXPORT_C TUid CBitwiseBitmap::Uid() const
sl@0
   111
	{
sl@0
   112
	return(iUid);
sl@0
   113
	}
sl@0
   114
sl@0
   115
EXPORT_C TInt CBitwiseBitmap::Construct(const TSize& aSize,TDisplayMode aDispMode,TUid aCreatorUid)
sl@0
   116
	{
sl@0
   117
	if (iHeap == NULL || iPile == NULL)
sl@0
   118
		return KErrNoMemory;
sl@0
   119
sl@0
   120
	if (aSize.iWidth > KMaxPixelSize || aSize.iHeight > KMaxPixelSize)
sl@0
   121
		return KErrTooBig;
sl@0
   122
sl@0
   123
	TUint8* data = NULL;
sl@0
   124
	Reset();
sl@0
   125
sl@0
   126
	iSettings.SetDisplayModes(aDispMode);
sl@0
   127
	iByteWidth = ByteWidth(aSize.iWidth,aDispMode);
sl@0
   128
sl@0
   129
	TInt64 hugeDataSize = TInt64(aSize.iHeight) * TInt64(iByteWidth);
sl@0
   130
	if (I64HIGH(hugeDataSize) != 0 || I64LOW(hugeDataSize) > KMaxByteSize)
sl@0
   131
		return KErrTooBig;
sl@0
   132
sl@0
   133
	TInt dataSize = I64LOW(hugeDataSize);
sl@0
   134
	iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + dataSize;
sl@0
   135
	iHeader.iStructSize = sizeof(SEpocBitmapHeader);
sl@0
   136
	iHeader.iSizeInPixels = aSize;
sl@0
   137
	iHeader.iSizeInTwips = TSize(0,0);
sl@0
   138
	iHeader.iBitsPerPixel = Bpp(aDispMode);
sl@0
   139
	iHeader.iColor = IsColor(aDispMode);
sl@0
   140
	iHeader.iPaletteEntries = 0;
sl@0
   141
	iHeader.iCompression = ENoBitmapCompression;
sl@0
   142
sl@0
   143
	if (aSize.iHeight && aSize.iWidth)
sl@0
   144
		{
sl@0
   145
		if(aCreatorUid!=KUidCFbsBitmapCreation)
sl@0
   146
			{
sl@0
   147
			RHardwareBitmap hwb;
sl@0
   148
			TAcceleratedBitmapInfo info;
sl@0
   149
			TInt ret = hwb.Create(aDispMode,aSize,aCreatorUid);
sl@0
   150
			if(ret==KErrNone)
sl@0
   151
				ret = hwb.GetInfo(info);
sl@0
   152
			if(ret!=KErrNone)
sl@0
   153
				{
sl@0
   154
				Reset();
sl@0
   155
				return ret;
sl@0
   156
				}
sl@0
   157
sl@0
   158
			iSettings.SetVolatileBitmap();
sl@0
   159
			data = info.iAddress;
sl@0
   160
			dataSize = info.iLinePitch*info.iSize.iHeight;
sl@0
   161
			__ASSERT_DEBUG(info.iLinePitch >= iByteWidth, ::Panic(EFbsHardwareBitmapError));
sl@0
   162
			iByteWidth = info.iLinePitch;
sl@0
   163
sl@0
   164
			iDataOffset = hwb.iHandle;	// iDataOffset = handle for hardware bitmap
sl@0
   165
			iUid.iUid = KCBitwiseBitmapHardwareUid.iUid;
sl@0
   166
#ifdef SYMBIAN_DISABLE_HARDWARE_BITMAP_WHITEFILL
sl@0
   167
			return KErrNone;
sl@0
   168
#endif
sl@0
   169
			}
sl@0
   170
		else
sl@0
   171
			{
sl@0
   172
			data = iPile->Alloc(dataSize);
sl@0
   173
			iDataOffset = data - iPile->ChunkBase();
sl@0
   174
			}
sl@0
   175
		if (!data)
sl@0
   176
			{
sl@0
   177
			iDataOffset=0;
sl@0
   178
			Reset();
sl@0
   179
			return(KErrNoMemory);	// no memory exit point
sl@0
   180
			}
sl@0
   181
		}
sl@0
   182
sl@0
   183
	if (dataSize < KMaxLargeBitmapAlloc || aDispMode == EColor4K || iUid.iUid == KCBitwiseBitmapHardwareUid.iUid)
sl@0
   184
		{
sl@0
   185
		WhiteFill(data,dataSize,aDispMode);
sl@0
   186
		}
sl@0
   187
sl@0
   188
	return KErrNone;	// success exit point
sl@0
   189
	}
sl@0
   190
sl@0
   191
sl@0
   192
EXPORT_C TInt CBitwiseBitmap::ConstructExtended(const TSize& aSize, TDisplayMode aDispMode, TUid aType, TInt aDataSize)
sl@0
   193
	{
sl@0
   194
	if (iHeap == NULL || iPile == NULL)
sl@0
   195
		return KErrNoMemory;
sl@0
   196
	if (aSize.iWidth > KMaxPixelSize || aSize.iHeight > KMaxPixelSize)
sl@0
   197
		return KErrTooBig;
sl@0
   198
	if (aType.iUid == KCBitwiseBitmapUid.iUid || aType.iUid == KCBitwiseBitmapHardwareUid.iUid)
sl@0
   199
		return KErrArgument; // make sure the extended bitmap type is not one of the standard types
sl@0
   200
	if (aDataSize > KMaxByteSize)
sl@0
   201
		return KErrTooBig;
sl@0
   202
	Reset();
sl@0
   203
	iUid = aType;
sl@0
   204
	iSettings.SetDisplayModes(aDispMode);
sl@0
   205
	iByteWidth = ByteWidth(aSize.iWidth, aDispMode);
sl@0
   206
	iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + aDataSize;
sl@0
   207
	iHeader.iStructSize = sizeof(SEpocBitmapHeader);
sl@0
   208
	iHeader.iSizeInPixels = aSize;
sl@0
   209
	iHeader.iSizeInTwips = TSize(0,0);
sl@0
   210
	iHeader.iBitsPerPixel = Bpp(aDispMode);
sl@0
   211
	iHeader.iColor = IsColor(aDispMode);
sl@0
   212
	iHeader.iPaletteEntries = 0;
sl@0
   213
	iHeader.iCompression = EProprietaryCompression;
sl@0
   214
	TUint8* data = iPile->Alloc(aDataSize);
sl@0
   215
	if (!data)
sl@0
   216
		{
sl@0
   217
		Reset();
sl@0
   218
		return KErrNoMemory;
sl@0
   219
		}
sl@0
   220
	iDataOffset = data - iPile->ChunkBase();
sl@0
   221
	return KErrNone;
sl@0
   222
	}
sl@0
   223
sl@0
   224
sl@0
   225
EXPORT_C void CBitwiseBitmap::ConstructL(RFs& aFs,const TDesC& aFilename,TInt32 aId,TUint aFileOffset)
sl@0
   226
	{
sl@0
   227
	//If aFileOffset != 0 then aFilename is a file with an embedded MBM file section at the end.
sl@0
   228
	//The implementation uses the fact that mbm files are implemented as
sl@0
   229
	//filestores and stream ID is actually the offset from the beginning of the filestore.
sl@0
   230
	//If stream ID changes its meaning in the future -
sl@0
   231
	//the method implementation has to be reviewed and changed too.
sl@0
   232
	User::LeaveIfNull(iHeap);
sl@0
   233
	User::LeaveIfNull(iPile);
sl@0
   234
	TUint fileMode = EFileRead;
sl@0
   235
	if(aFileOffset != 0) //This is a file with an embedded MBM file section at the end.
sl@0
   236
		fileMode |= EFileShareReadersOnly;
sl@0
   237
	CShiftedFileStore* filestore = CShiftedFileStore::OpenLC(aFs,aFilename,fileMode,aFileOffset);
sl@0
   238
	TStreamId streamid = filestore->Root();
sl@0
   239
	//TStreamId is the offset from the beggining of the file.
sl@0
   240
	//Obviously, if the bitmap file section is at the middle of the physical file,
sl@0
   241
	//we should add aFileOffset value to TStreamId value and use it.
sl@0
   242
	TStreamId streamid2(streamid.Value() + aFileOffset);
sl@0
   243
	RStoreReadStream readstream;
sl@0
   244
	readstream.OpenLC(*filestore,streamid2);
sl@0
   245
	TInt numbitmaps = readstream.ReadInt32L();
sl@0
   246
	if (aId < 0 || aId >= numbitmaps)
sl@0
   247
		User::Leave(KErrEof);
sl@0
   248
sl@0
   249
	TStreamId bmpstreamid;
sl@0
   250
	bmpstreamid.InternalizeL(readstream);
sl@0
   251
	TStreamId bmpstreamid2(bmpstreamid.Value() + aFileOffset);
sl@0
   252
	for (TInt count = 0; count < aId; count++)
sl@0
   253
		{
sl@0
   254
		bmpstreamid2.InternalizeL(readstream);
sl@0
   255
		bmpstreamid2 = TStreamId(bmpstreamid2.Value() + aFileOffset);
sl@0
   256
		}
sl@0
   257
sl@0
   258
	CleanupStack::PopAndDestroy();
sl@0
   259
	RStoreReadStream bmpstream;
sl@0
   260
	bmpstream.OpenLC(*filestore,bmpstreamid2);
sl@0
   261
	InternalizeL(bmpstream);
sl@0
   262
	CleanupStack::PopAndDestroy(2);
sl@0
   263
	}
sl@0
   264
sl@0
   265
EXPORT_C void CBitwiseBitmap::ConstructL(RFile& aFile,TInt32 aId,TUint aFileOffset)
sl@0
   266
	{
sl@0
   267
	//If aFileOffset != 0 then aFilename is a file with an embedded MBM file section at the end.
sl@0
   268
	//The implementation uses the fact that mbm files are implemented as
sl@0
   269
	//filestores and stream ID is actually the offset from the beginning of the filestore.
sl@0
   270
	//If stream ID changes its meaning in the future -
sl@0
   271
	//the method implementation has to be reviewed and changed too.
sl@0
   272
	User::LeaveIfNull(iHeap);
sl@0
   273
	User::LeaveIfNull(iPile);
sl@0
   274
sl@0
   275
	CShiftedFileStore* filestore = CShiftedFileStore::FromL(aFile,aFileOffset);
sl@0
   276
	CleanupStack::PushL(filestore);
sl@0
   277
	TStreamId streamid = filestore->Root();
sl@0
   278
	//TStreamId is the offset from the beggining of the file.
sl@0
   279
	//Obviously, if the bitmap file section is at the middle of the physical file,
sl@0
   280
	//we should add aFileOffset value to TStreamId value and use it.
sl@0
   281
	TStreamId streamid2(streamid.Value() + aFileOffset);
sl@0
   282
	RStoreReadStream readstream;
sl@0
   283
	readstream.OpenLC(*filestore,streamid2);
sl@0
   284
	TInt numbitmaps = readstream.ReadInt32L();
sl@0
   285
	if (aId < 0 || aId >= numbitmaps)
sl@0
   286
		User::Leave(KErrEof);
sl@0
   287
	//Retrieving the streamid of the bitmap of that id from the file
sl@0
   288
	TStreamId bmpstreamid;
sl@0
   289
	bmpstreamid.InternalizeL(readstream);
sl@0
   290
	TStreamId bmpstreamid2(bmpstreamid.Value() + aFileOffset);
sl@0
   291
	for (TInt count = 0; count < aId; count++)
sl@0
   292
		{
sl@0
   293
		bmpstreamid2.InternalizeL(readstream);
sl@0
   294
		bmpstreamid2 = TStreamId(bmpstreamid2.Value() + aFileOffset);
sl@0
   295
		}
sl@0
   296
	//Use the streamid found to initialize the bitmap raw data in the memory
sl@0
   297
	CleanupStack::PopAndDestroy(&readstream);
sl@0
   298
	RStoreReadStream bmpstream;
sl@0
   299
	bmpstream.OpenLC(*filestore,bmpstreamid2);
sl@0
   300
	InternalizeL(bmpstream);
sl@0
   301
	CleanupStack::PopAndDestroy(2,filestore);
sl@0
   302
	}
sl@0
   303
sl@0
   304
sl@0
   305
EXPORT_C void CBitwiseBitmap::ConstructL(CShiftedFileStore* aFileStore,TStreamId aStreamId)
sl@0
   306
	{
sl@0
   307
	User::LeaveIfNull(iHeap);
sl@0
   308
	User::LeaveIfNull(iPile);
sl@0
   309
sl@0
   310
	RStoreReadStream bmpstream;
sl@0
   311
	bmpstream.OpenLC(*aFileStore,aStreamId);
sl@0
   312
	InternalizeL(bmpstream);
sl@0
   313
	CleanupStack::PopAndDestroy();
sl@0
   314
	}
sl@0
   315
sl@0
   316
EXPORT_C TInt CBitwiseBitmap::CopyData(const CBitwiseBitmap& aSourceBitmap)
sl@0
   317
	{
sl@0
   318
	__ASSERT_DEBUG(iHeap && iPile, ::Panic(EFbsPanicBitmapDataCopy));
sl@0
   319
	__ASSERT_DEBUG(!iIsCompressedInRAM, ::Panic(EFbsPanicBitmapDataCopy));
sl@0
   320
	__ASSERT_DEBUG(iUid.iUid == KCBitwiseBitmapUid.iUid, ::Panic(EFbsPanicBitmapDataCopy));
sl@0
   321
	if (aSourceBitmap.iUid.iUid != KCBitwiseBitmapUid.iUid)
sl@0
   322
		return KErrNotSupported;
sl@0
   323
	const TDisplayMode displayMode = aSourceBitmap.iSettings.CurrentDisplayMode();
sl@0
   324
	__ASSERT_DEBUG(iSettings.CurrentDisplayMode() == displayMode, ::Panic(EFbsPanicBitmapDataCopy));
sl@0
   325
	if (aSourceBitmap.iHeader.iSizeInPixels.iWidth > 0)
sl@0
   326
		iHeader.iSizeInTwips.iWidth = (aSourceBitmap.iHeader.iSizeInTwips.iWidth * iHeader.iSizeInPixels.iWidth)
sl@0
   327
			/ aSourceBitmap.iHeader.iSizeInPixels.iWidth;
sl@0
   328
	if (aSourceBitmap.iHeader.iSizeInPixels.iHeight > 0)
sl@0
   329
		iHeader.iSizeInTwips.iHeight = (aSourceBitmap.iHeader.iSizeInTwips.iHeight * iHeader.iSizeInPixels.iHeight)
sl@0
   330
			/ aSourceBitmap.iHeader.iSizeInPixels.iHeight;
sl@0
   331
	TUint32* destBase = DataAddress();
sl@0
   332
	TUint32* srcBase = aSourceBitmap.DataAddress();
sl@0
   333
	if (!destBase || !srcBase)
sl@0
   334
		return KErrNone;
sl@0
   335
	TInt minPixelHeight = Min(iHeader.iSizeInPixels.iHeight, aSourceBitmap.iHeader.iSizeInPixels.iHeight);
sl@0
   336
	if (aSourceBitmap.iIsCompressedInRAM)
sl@0
   337
		{
sl@0
   338
		TUint8* dest = (TUint8*)destBase;
sl@0
   339
		TInt minPixelWidth = Min(iHeader.iSizeInPixels.iWidth, aSourceBitmap.iHeader.iSizeInPixels.iWidth);
sl@0
   340
		TPtr8 pDest(dest, iByteWidth, iByteWidth);
sl@0
   341
		TPoint pt(0, 0);
sl@0
   342
		TPoint ditherOffset(0, 0);
sl@0
   343
		TLineScanningPosition scanPos(srcBase);
sl@0
   344
		scanPos.iScanLineBuffer = HBufC8::New(aSourceBitmap.iByteWidth + 4);
sl@0
   345
		if (!scanPos.iScanLineBuffer)
sl@0
   346
			return KErrNoMemory;
sl@0
   347
		for (TInt row = 0; row < minPixelHeight; ++row)
sl@0
   348
			{
sl@0
   349
			pDest.Set(dest, iByteWidth, iByteWidth);
sl@0
   350
			pt.iY = row;
sl@0
   351
			aSourceBitmap.GetScanLine(pDest, pt, minPixelWidth, EFalse, ditherOffset, displayMode, srcBase, scanPos);
sl@0
   352
			dest += iByteWidth;
sl@0
   353
			}
sl@0
   354
		delete scanPos.iScanLineBuffer;
sl@0
   355
		}
sl@0
   356
	else
sl@0
   357
		{
sl@0
   358
		TUint8* dest = (TUint8*)destBase;
sl@0
   359
		TUint8* src = (TUint8*)srcBase;
sl@0
   360
		TInt minByteWidth = Min(iByteWidth, aSourceBitmap.iByteWidth);
sl@0
   361
		for(TInt row = 0; row < minPixelHeight; ++row)
sl@0
   362
			{
sl@0
   363
			Mem::Copy(dest, src, minByteWidth);
sl@0
   364
			dest += iByteWidth;
sl@0
   365
			src += aSourceBitmap.iByteWidth;
sl@0
   366
			}
sl@0
   367
		}
sl@0
   368
	if (iHeader.iSizeInPixels.iWidth > aSourceBitmap.iHeader.iSizeInPixels.iWidth)
sl@0
   369
		{
sl@0
   370
		TInt extraBits = (aSourceBitmap.iHeader.iSizeInPixels.iWidth * aSourceBitmap.iHeader.iBitsPerPixel) & 31;
sl@0
   371
		if (extraBits > 0)
sl@0
   372
			{
sl@0
   373
			TUint32 mask = KMaxTUint32;
sl@0
   374
			mask <<= extraBits;
sl@0
   375
			TInt destWordWidth = iByteWidth >> 2;
sl@0
   376
			TInt srcWordWidth = aSourceBitmap.iByteWidth >> 2;
sl@0
   377
			TUint32* maskAddress = destBase + srcWordWidth - 1;
sl@0
   378
			for (TInt row = 0; row < minPixelHeight; ++row)
sl@0
   379
				{
sl@0
   380
				*maskAddress |= mask;
sl@0
   381
				maskAddress += destWordWidth;
sl@0
   382
				}
sl@0
   383
			}
sl@0
   384
		}
sl@0
   385
	return KErrNone;
sl@0
   386
	}
sl@0
   387
sl@0
   388
EXPORT_C void CBitwiseBitmap::ExternalizeL(RWriteStream& aStream,const CFbsBitmap& aHandleBitmap) const
sl@0
   389
	{
sl@0
   390
	ExternalizeRectangleL(aStream,iHeader.iSizeInPixels,aHandleBitmap);
sl@0
   391
	}
sl@0
   392
sl@0
   393
EXPORT_C void CBitwiseBitmap::ExternalizeRectangleL(RWriteStream& aStream,const TRect& aRect,const CFbsBitmap& aHandleBitmap) const
sl@0
   394
	{
sl@0
   395
	if (aRect.IsEmpty())
sl@0
   396
		User::Leave(KErrArgument);
sl@0
   397
	// the bitmap must have been already prepared for data access
sl@0
   398
	if (aHandleBitmap.iUseCount == 0)
sl@0
   399
		User::Leave(KErrArgument);
sl@0
   400
sl@0
   401
	// If the bitmap is palette-compressed in RAM externalisation is currently not supported
sl@0
   402
	// Externalisation of extended bitmaps is currently not supported either
sl@0
   403
	if (iHeader.iCompression == EGenericPaletteCompression || iHeader.iCompression == EProprietaryCompression)
sl@0
   404
		User::Leave(KErrNotSupported);
sl@0
   405
	const TRect bitmapRect(iHeader.iSizeInPixels);
sl@0
   406
	TRect sourceRect(aRect);
sl@0
   407
	if (!sourceRect.Intersects(bitmapRect))
sl@0
   408
		User::Leave(KErrTooBig);
sl@0
   409
	sourceRect.Intersection(bitmapRect);
sl@0
   410
sl@0
   411
	TDisplayMode displayMode = iSettings.CurrentDisplayMode();
sl@0
   412
	const TInt scanLineByteLength = CBitwiseBitmap::ByteWidth(sourceRect.Width(),displayMode);
sl@0
   413
	const TInt rectByteSize = sourceRect.Height() * scanLineByteLength;
sl@0
   414
	TUint8* buffer = (TUint8*)User::AllocLC(scanLineByteLength);
sl@0
   415
sl@0
   416
	TPtr8 scanline(buffer,scanLineByteLength,scanLineByteLength);
sl@0
   417
	scanline.Fill(0xff);
sl@0
   418
	const TPoint zeroPoint;
sl@0
   419
	TInt compressedSize = 0;
sl@0
   420
	TInt row;
sl@0
   421
sl@0
   422
	for (row = sourceRect.iTl.iY; row < sourceRect.iBr.iY; row++)
sl@0
   423
		{
sl@0
   424
		GetScanLine(scanline,TPoint(sourceRect.iTl.iX,row),sourceRect.Width(),EFalse,zeroPoint,displayMode,aHandleBitmap.DataAddress());
sl@0
   425
		compressedSize += SizeOfDataCompressed(buffer,scanLineByteLength);
sl@0
   426
		}
sl@0
   427
sl@0
   428
	TBool compress = EFalse;
sl@0
   429
	if(compressedSize > 0)
sl@0
   430
		{
sl@0
   431
		compress = (displayMode == EColor4K) || (compressedSize < (rectByteSize >> 1) + (rectByteSize >> 2));
sl@0
   432
		}
sl@0
   433
sl@0
   434
	aStream.WriteInt32L(sizeof(SEpocBitmapHeader) + ((compress) ? compressedSize : rectByteSize));
sl@0
   435
	aStream.WriteInt32L(iHeader.iStructSize);
sl@0
   436
	aStream.WriteInt32L(sourceRect.Width());
sl@0
   437
	aStream.WriteInt32L(sourceRect.Height());
sl@0
   438
	aStream.WriteInt32L(HorizontalPixelsToTwips(sourceRect.Width()));
sl@0
   439
	aStream.WriteInt32L(VerticalPixelsToTwips(sourceRect.Height()));
sl@0
   440
	aStream.WriteInt32L(iHeader.iBitsPerPixel);
sl@0
   441
	aStream.WriteUint32L(iHeader.iColor);
sl@0
   442
	aStream.WriteInt32L(0);
sl@0
   443
	aStream.WriteUint32L(compress ? CompressionType(iHeader.iBitsPerPixel, iHeader.iColor) : ENoBitmapCompression);
sl@0
   444
sl@0
   445
	for (row = sourceRect.iTl.iY; row < sourceRect.iBr.iY; row++)
sl@0
   446
		{
sl@0
   447
		GetScanLine(scanline,TPoint(sourceRect.iTl.iX,row),sourceRect.Width(),EFalse,zeroPoint,displayMode,aHandleBitmap.DataAddress());
sl@0
   448
sl@0
   449
		if (!compress)
sl@0
   450
			aStream.WriteL(buffer,scanLineByteLength);
sl@0
   451
		else
sl@0
   452
			DoExternalizeDataCompressedL(aStream,buffer,scanLineByteLength);
sl@0
   453
		}
sl@0
   454
sl@0
   455
	CleanupStack::PopAndDestroy(); // buffer
sl@0
   456
	}
sl@0
   457
sl@0
   458
EXPORT_C void CBitwiseBitmap::InternalizeHeaderL(RReadStream& aStream,SEpocBitmapHeader& aHeader)
sl@0
   459
	{
sl@0
   460
	aHeader.iBitmapSize=aStream.ReadInt32L();
sl@0
   461
	aHeader.iStructSize=aStream.ReadInt32L();
sl@0
   462
	if (aHeader.iStructSize!=sizeof(SEpocBitmapHeader)) User::Leave(KErrCorrupt);
sl@0
   463
	aHeader.iSizeInPixels.iWidth=aStream.ReadInt32L();
sl@0
   464
	aHeader.iSizeInPixels.iHeight=aStream.ReadInt32L();
sl@0
   465
	aHeader.iSizeInTwips.iWidth=aStream.ReadInt32L();
sl@0
   466
	aHeader.iSizeInTwips.iHeight=aStream.ReadInt32L();
sl@0
   467
	aHeader.iBitsPerPixel=aStream.ReadInt32L();
sl@0
   468
	aHeader.iColor=(TInt)aStream.ReadUint32L();
sl@0
   469
	aHeader.iPaletteEntries=aStream.ReadInt32L();
sl@0
   470
	if (aHeader.iPaletteEntries != 0)
sl@0
   471
		{
sl@0
   472
		//Palettes are not supported.
sl@0
   473
		User::Leave(KErrNotSupported);
sl@0
   474
		}
sl@0
   475
	aHeader.iCompression=(TBitmapfileCompression)aStream.ReadUint32L();
sl@0
   476
	CheckHeaderIsValidL(aHeader);
sl@0
   477
	}
sl@0
   478
sl@0
   479
void CBitwiseBitmap::CheckHeaderIsValidL(const SEpocBitmapHeader& aHeader)	
sl@0
   480
	{
sl@0
   481
	//These fields are signed in the structure?
sl@0
   482
	TInt bitmapSize = aHeader.iBitmapSize;
sl@0
   483
	TInt imageHeightPix = aHeader.iSizeInPixels.iHeight;
sl@0
   484
	TInt imageWidthPix = aHeader.iSizeInPixels.iWidth;
sl@0
   485
	TInt bitsPerPixel = aHeader.iBitsPerPixel;
sl@0
   486
	TInt compression = aHeader.iCompression;
sl@0
   487
	TInt colour = aHeader.iColor;
sl@0
   488
	TBool corruptFlag = EFalse;
sl@0
   489
	
sl@0
   490
	//Need to copy the values from the structure
sl@0
   491
	TDisplayMode equivalentMode = CBitwiseBitmap::DisplayMode(aHeader.iBitsPerPixel,aHeader.iColor);
sl@0
   492
	if (equivalentMode == ENone)
sl@0
   493
		{
sl@0
   494
		User::Leave(KErrNotSupported);	
sl@0
   495
		}
sl@0
   496
	if(aHeader.iColor < 0)
sl@0
   497
		 {
sl@0
   498
		 corruptFlag = ETrue;
sl@0
   499
		 } 
sl@0
   500
	 	//easieast way to check if compression type is appropriate is to ask the compressor 
sl@0
   501
	if (compression && compression!= CBitwiseBitmap::CompressionType(bitsPerPixel,colour))
sl@0
   502
		{
sl@0
   503
		corruptFlag = ETrue;
sl@0
   504
		}
sl@0
   505
	//danger when using CBitwiseBitmap is they could panic for bad input...
sl@0
   506
	if (imageHeightPix <= 0 || imageWidthPix <= 0 || bitsPerPixel <= 0)
sl@0
   507
		{
sl@0
   508
		corruptFlag = ETrue;
sl@0
   509
		}
sl@0
   510
	const TInt KMeg = 1024 * 1024;
sl@0
   511
	//Test that scanline bytes calculation won't overflow.
sl@0
   512
	TInt bytesPerPack;	// pixel size in memory
sl@0
   513
	TInt bytesPerCompression;	// compressed unit data size
sl@0
   514
    User::LeaveIfError(CompressedFormatInfo(equivalentMode, bytesPerPack, bytesPerCompression));
sl@0
   515
	if (imageWidthPix > 2047 * KMeg / bytesPerPack)
sl@0
   516
		{
sl@0
   517
		corruptFlag = ETrue;
sl@0
   518
		}
sl@0
   519
	TInt uncompressedWidthBytes = CBitwiseBitmap::ByteWidth(imageWidthPix,equivalentMode);	//we know this won't overflow, now.
sl@0
   520
	//use top set bit indexes of 32 bit integer values to estimate when W*H multiply will overflow
sl@0
   521
	TInt exponentWidth = 0;
sl@0
   522
	TInt exponentHeight = 0;
sl@0
   523
	if (uncompressedWidthBytes & 0xffff0000)
sl@0
   524
		{
sl@0
   525
		exponentWidth += 16;
sl@0
   526
		}
sl@0
   527
	if (imageHeightPix & 0xffff0000)
sl@0
   528
		{
sl@0
   529
		exponentHeight += 16;
sl@0
   530
		}
sl@0
   531
	if (exponentWidth || exponentHeight)
sl@0
   532
		{
sl@0
   533
		if (uncompressedWidthBytes & 0xFF00FF00)
sl@0
   534
			{
sl@0
   535
			exponentWidth += 8;
sl@0
   536
			}
sl@0
   537
		if (imageHeightPix & 0xFF00FF00)
sl@0
   538
			{
sl@0
   539
			exponentHeight += 8;
sl@0
   540
			}
sl@0
   541
		if (uncompressedWidthBytes & 0xf0f0f0f0)
sl@0
   542
			{
sl@0
   543
			exponentWidth += 4;
sl@0
   544
			}
sl@0
   545
		if (imageHeightPix & 0xf0f0f0f0)
sl@0
   546
			{
sl@0
   547
			exponentHeight += 4;
sl@0
   548
			}
sl@0
   549
		if (uncompressedWidthBytes & 0xCCCCCCCC)
sl@0
   550
			{
sl@0
   551
			exponentWidth += 2;
sl@0
   552
			}
sl@0
   553
		if (imageHeightPix & 0xCCCCCCCC)
sl@0
   554
			{
sl@0
   555
				exponentHeight += 2;
sl@0
   556
		}
sl@0
   557
		if (uncompressedWidthBytes & 0xaaaaaaaa)
sl@0
   558
			{
sl@0
   559
			exponentWidth += 1;
sl@0
   560
			}
sl@0
   561
		if (imageHeightPix & 0xaaaaaaaa)
sl@0
   562
			{
sl@0
   563
			exponentHeight += 1;
sl@0
   564
			}
sl@0
   565
		TInt exponentTotal = exponentWidth + exponentHeight;
sl@0
   566
		if (exponentTotal >= 31)
sl@0
   567
			{
sl@0
   568
			//The result would defuinitely exceed a signed int
sl@0
   569
			corruptFlag = ETrue;
sl@0
   570
			}
sl@0
   571
		else if (exponentTotal == 30)
sl@0
   572
			{
sl@0
   573
			//as a bit test, both "next most significat bits" must be set to cause a carry-over,
sl@0
   574
			//but that isn't so trivial to test.
sl@0
   575
			if ((uncompressedWidthBytes >> 1) * imageHeightPix > 1024 * KMeg)
sl@0
   576
				{
sl@0
   577
				corruptFlag = ETrue;
sl@0
   578
				}
sl@0
   579
			}
sl@0
   580
		}
sl@0
   581
	if (compression)
sl@0
   582
		{
sl@0
   583
		/* estimate compressed file size limits
sl@0
   584
		byte compression uses lead code 0..127 = repeat next byte n+1 times. -1..-128 = copy next -n bytes
sl@0
   585
		16, 24, 32 use byte lead codes as above followed by words, triplets, or dwords
sl@0
   586
		1,2,4,8,16 all encode any dword alignment buffer padding data as full data values.
sl@0
   587
		32 doesn't have padding issue. 24 does not encode padding bytes.
sl@0
   588
		12 bit compression uses 0..15 spare nibble to encode short runs. 0=unique. Can never make file bigger.*/
sl@0
   589
		if (bitsPerPixel == 12)
sl@0
   590
			{
sl@0
   591
			//min file size is 1/16 of rect size
sl@0
   592
			if (bitmapSize < sizeof(SEpocBitmapHeader) + ((uncompressedWidthBytes * imageHeightPix) / 16))
sl@0
   593
				{
sl@0
   594
				corruptFlag = ETrue;	
sl@0
   595
				}
sl@0
   596
			if (bitmapSize > sizeof(SEpocBitmapHeader) + uncompressedWidthBytes * imageHeightPix)
sl@0
   597
				{
sl@0
   598
				corruptFlag = ETrue;
sl@0
   599
				}
sl@0
   600
			}
sl@0
   601
		else
sl@0
   602
			{
sl@0
   603
				TInt packedValsPerFile = (uncompressedWidthBytes / bytesPerPack) * imageHeightPix;
sl@0
   604
				//for some of the compressors 0 means a run of 2, so max 127 means a run of 129
sl@0
   605
				TInt estMinCompressedBlocksPerFile = (packedValsPerFile - 1) / 129 + 1;	
sl@0
   606
				/* Absolute minimum is blocks of 128 repeats possibly spanning multiple scanlines
sl@0
   607
				This can't be compressed by the current per-scanline compressor,
sl@0
   608
				but is acceptable to the decompressor. */
sl@0
   609
				if (bitmapSize < sizeof(SEpocBitmapHeader) + estMinCompressedBlocksPerFile * (bytesPerCompression + 1))
sl@0
   610
					{
sl@0
   611
					corruptFlag = ETrue;
sl@0
   612
					}
sl@0
   613
			/* Absolute maximum is to store every pixel as a seperate run of 1 byte.
sl@0
   614
			The current compressor would never do this... but the file is legal! */
sl@0
   615
				if (bitmapSize > sizeof(SEpocBitmapHeader) + packedValsPerFile * (bytesPerCompression + 1))
sl@0
   616
					{
sl@0
   617
					corruptFlag = ETrue;
sl@0
   618
					}
sl@0
   619
			}
sl@0
   620
		}
sl@0
   621
	else
sl@0
   622
		{
sl@0
   623
		if (bitmapSize != sizeof(SEpocBitmapHeader) + uncompressedWidthBytes * imageHeightPix)
sl@0
   624
			{
sl@0
   625
			corruptFlag = ETrue;
sl@0
   626
			}
sl@0
   627
		}
sl@0
   628
	if(corruptFlag)
sl@0
   629
		{
sl@0
   630
		User::Leave(KErrCorrupt);
sl@0
   631
		}
sl@0
   632
			
sl@0
   633
	}
sl@0
   634
sl@0
   635
/**
sl@0
   636
Internalizes the bit map contents from a stream.
sl@0
   637
@param aStream The read stream containing the bit map.
sl@0
   638
*/
sl@0
   639
EXPORT_C void CBitwiseBitmap::InternalizeL(RReadStream& aStream)
sl@0
   640
	{
sl@0
   641
	if (iHeap==NULL || iPile==NULL)
sl@0
   642
		User::Leave(KErrNoMemory);
sl@0
   643
	Reset();
sl@0
   644
	InternalizeHeaderL(aStream,iHeader);
sl@0
   645
sl@0
   646
	TDisplayMode displayMode = DisplayMode(iHeader.iBitsPerPixel,iHeader.iColor);
sl@0
   647
	if(displayMode == ENone)
sl@0
   648
		{
sl@0
   649
		Reset();
sl@0
   650
		User::Leave(KErrCorrupt);
sl@0
   651
		}
sl@0
   652
sl@0
   653
	iSettings.SetDisplayModes(displayMode);
sl@0
   654
sl@0
   655
	iByteWidth = ByteWidth(iHeader.iSizeInPixels.iWidth,iSettings.CurrentDisplayMode());
sl@0
   656
sl@0
   657
	TUint8* data=NULL;
sl@0
   658
	TInt bytesize = iByteWidth * iHeader.iSizeInPixels.iHeight;
sl@0
   659
	if (bytesize > 0)
sl@0
   660
		{
sl@0
   661
		data = iPile->Alloc(bytesize);
sl@0
   662
		iDataOffset = data - iPile->ChunkBase();
sl@0
   663
		if (!data)
sl@0
   664
			{
sl@0
   665
			iDataOffset=0;
sl@0
   666
			Reset();
sl@0
   667
			User::LeaveNoMemory();
sl@0
   668
			}
sl@0
   669
		}
sl@0
   670
	TRAPD(err,DoInternalizeL(aStream,iHeader.iBitmapSize-iHeader.iStructSize,DataAddress()));
sl@0
   671
	if (err!=KErrNone)
sl@0
   672
		{
sl@0
   673
		Reset();
sl@0
   674
		User::Leave(err);
sl@0
   675
		}
sl@0
   676
	}
sl@0
   677
sl@0
   678
sl@0
   679
void CBitwiseBitmap::DoInternalizeL(RReadStream& aStream,TInt aSrceSize,TUint32* aBase)
sl@0
   680
	{
sl@0
   681
	if (iHeader.iCompression==ENoBitmapCompression)
sl@0
   682
		aStream.ReadL((TUint8*)aBase,aSrceSize);
sl@0
   683
	else if (iHeader.iCompression < ERLECompressionLast)
sl@0
   684
		{
sl@0
   685
		TBitmapfileCompression compression = iHeader.iCompression;
sl@0
   686
		iHeader.iCompression = ENoBitmapCompression;
sl@0
   687
		iHeader.iBitmapSize = iByteWidth*iHeader.iSizeInPixels.iHeight+sizeof(SEpocBitmapHeader);
sl@0
   688
		DoInternalizeCompressedDataL(aStream,aSrceSize,aBase,compression);
sl@0
   689
		}
sl@0
   690
 	else
sl@0
   691
		CheckHeaderIsValidL(iHeader);
sl@0
   692
	}
sl@0
   693
sl@0
   694
EXPORT_C TDisplayMode CBitwiseBitmap::DisplayMode() const
sl@0
   695
	{
sl@0
   696
	return iSettings.CurrentDisplayMode();
sl@0
   697
	}
sl@0
   698
sl@0
   699
EXPORT_C TInt CBitwiseBitmap::HorizontalPixelsToTwips(TInt aPixels) const
sl@0
   700
	{
sl@0
   701
	if (iHeader.iSizeInPixels.iWidth==0)
sl@0
   702
		return(0);
sl@0
   703
	TInt twips;
sl@0
   704
	twips = (aPixels*iHeader.iSizeInTwips.iWidth+(iHeader.iSizeInPixels.iWidth/2))/iHeader.iSizeInPixels.iWidth;
sl@0
   705
	return(twips);
sl@0
   706
	}
sl@0
   707
sl@0
   708
EXPORT_C TInt CBitwiseBitmap::VerticalPixelsToTwips(TInt aPixels) const
sl@0
   709
	{
sl@0
   710
	if (iHeader.iSizeInPixels.iHeight==0)
sl@0
   711
		return(0);
sl@0
   712
	TInt twips;
sl@0
   713
	twips = (aPixels*iHeader.iSizeInTwips.iHeight+(iHeader.iSizeInPixels.iHeight/2))/iHeader.iSizeInPixels.iHeight;
sl@0
   714
	return (twips);
sl@0
   715
	}
sl@0
   716
sl@0
   717
EXPORT_C TSize CBitwiseBitmap::SizeInPixels() const
sl@0
   718
	{
sl@0
   719
	return(iHeader.iSizeInPixels);
sl@0
   720
	}
sl@0
   721
sl@0
   722
EXPORT_C TSize CBitwiseBitmap::SizeInTwips() const
sl@0
   723
	{
sl@0
   724
	return(iHeader.iSizeInTwips);
sl@0
   725
	}
sl@0
   726
sl@0
   727
EXPORT_C TInt CBitwiseBitmap::HorizontalTwipsToPixels(TInt aTwips) const
sl@0
   728
	{
sl@0
   729
	if (iHeader.iSizeInTwips.iWidth==0)
sl@0
   730
		return(0);
sl@0
   731
	TInt pixels;
sl@0
   732
	pixels = (aTwips*iHeader.iSizeInPixels.iWidth+(iHeader.iSizeInTwips.iWidth/2))/iHeader.iSizeInTwips.iWidth;
sl@0
   733
	return(pixels);
sl@0
   734
	}
sl@0
   735
sl@0
   736
EXPORT_C TInt CBitwiseBitmap::VerticalTwipsToPixels(TInt aTwips) const
sl@0
   737
	{
sl@0
   738
	if (iHeader.iSizeInTwips.iHeight==0)
sl@0
   739
		return(0);
sl@0
   740
	TInt pixels;
sl@0
   741
	pixels = (aTwips*iHeader.iSizeInPixels.iHeight+(iHeader.iSizeInTwips.iHeight/2))/iHeader.iSizeInTwips.iHeight;
sl@0
   742
	return(pixels);
sl@0
   743
	}
sl@0
   744
sl@0
   745
/**
sl@0
   746
The method retrieves the red, green, blue (RGB) color value of the pixel with
sl@0
   747
specified coordinates.
sl@0
   748
Note: The method works for uncompressed bitmaps and extended bitmaps only.
sl@0
   749
@internalComponent
sl@0
   750
@released
sl@0
   751
@pre aBase != NULL;
sl@0
   752
@param aColor It will be initialized with the pixel color value on success, otherwise
sl@0
   753
aColor value will be left unchanged.
sl@0
   754
@param aPixel Pixel coordinates.
sl@0
   755
@param aBase It points to the beginning of the bitmap data.
sl@0
   756
*/
sl@0
   757
EXPORT_C void CBitwiseBitmap::GetPixel(TRgb& aColor,const TPoint& aPixel,TUint32* aBase, CFbsRasterizer* aRasterizer) const
sl@0
   758
	{
sl@0
   759
	// This operation is not currently supported for compressed bitmaps.
sl@0
   760
	if (iHeader.iCompression != ENoBitmapCompression && iHeader.iCompression != EProprietaryCompression)
sl@0
   761
		{
sl@0
   762
		__ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
sl@0
   763
		return;
sl@0
   764
		}
sl@0
   765
	if (!iDataOffset)
sl@0
   766
		return;
sl@0
   767
sl@0
   768
	TInt x=aPixel.iX,y=aPixel.iY;
sl@0
   769
	if (x < -iHeader.iSizeInPixels.iWidth)
sl@0
   770
		x %= iHeader.iSizeInPixels.iWidth;
sl@0
   771
	if (y < -iHeader.iSizeInPixels.iHeight)
sl@0
   772
		y %= iHeader.iSizeInPixels.iHeight;
sl@0
   773
	if (x < 0)
sl@0
   774
		x += iHeader.iSizeInPixels.iWidth;
sl@0
   775
	if (y < 0)
sl@0
   776
		y += iHeader.iSizeInPixels.iHeight;
sl@0
   777
sl@0
   778
	if (iHeader.iCompression == EProprietaryCompression)
sl@0
   779
		{
sl@0
   780
		if (aRasterizer)
sl@0
   781
			{
sl@0
   782
			TUint32* slptr = const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(x,y), 1));
sl@0
   783
			if (slptr)
sl@0
   784
				{
sl@0
   785
				aColor = GetRgbPixelEx(x, slptr);
sl@0
   786
				}
sl@0
   787
			else
sl@0
   788
				{
sl@0
   789
				// wrong rasterizer for this extended bitmap - return white pixel
sl@0
   790
				aColor = KRgbWhite;
sl@0
   791
				}
sl@0
   792
			}
sl@0
   793
		else
sl@0
   794
			{
sl@0
   795
			// no rasterizer - return white pixel
sl@0
   796
			aColor = KRgbWhite;
sl@0
   797
			}
sl@0
   798
		}
sl@0
   799
	else
sl@0
   800
		{
sl@0
   801
		aColor = GetRgbPixelEx(x,ScanLineAddress(aBase,y));
sl@0
   802
		}
sl@0
   803
	}
sl@0
   804
sl@0
   805
EXPORT_C TInt CBitwiseBitmap::GetScanLinePtr(TUint32*& aSlptr, TInt& aLength,TPoint& aPixel,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
sl@0
   806
	{
sl@0
   807
	if (!iDataOffset)
sl@0
   808
		return KErrNone;
sl@0
   809
	if (aPixel.iX >= iHeader.iSizeInPixels.iWidth || aPixel.iX < -iHeader.iSizeInPixels.iWidth)
sl@0
   810
		aPixel.iX %= iHeader.iSizeInPixels.iWidth;
sl@0
   811
	if (aPixel.iY >= iHeader.iSizeInPixels.iHeight || aPixel.iY < -iHeader.iSizeInPixels.iHeight)
sl@0
   812
		aPixel.iY %= iHeader.iSizeInPixels.iHeight;
sl@0
   813
	if (aPixel.iX < 0)
sl@0
   814
		aPixel.iX += iHeader.iSizeInPixels.iWidth;
sl@0
   815
	if (aPixel.iY < 0)
sl@0
   816
		aPixel.iY += iHeader.iSizeInPixels.iHeight;
sl@0
   817
	if (aPixel.iX + aLength > iHeader.iSizeInPixels.iWidth)
sl@0
   818
		aLength = iHeader.iSizeInPixels.iWidth - aPixel.iX;
sl@0
   819
	if (iHeader.iCompression != ENoBitmapCompression)
sl@0
   820
		{
sl@0
   821
		return DoGetScanLinePtr(aSlptr, aPixel,aLength,aBase,aLineScanningPosition);
sl@0
   822
		}
sl@0
   823
	else
sl@0
   824
		{
sl@0
   825
		aSlptr = ScanLineAddress(aBase,aPixel.iY);
sl@0
   826
		}
sl@0
   827
	return KErrNone;
sl@0
   828
	}
sl@0
   829
sl@0
   830
EXPORT_C TInt CBitwiseBitmap::GetScanLinePtr(TUint32*& aSlptr, TPoint& aPixel,TInt aLength,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
sl@0
   831
	{
sl@0
   832
	return GetScanLinePtr(aSlptr, aLength,aPixel,aBase, aLineScanningPosition);
sl@0
   833
	}
sl@0
   834
sl@0
   835
TUint8 CBitwiseBitmap::GetGrayPixelEx(TInt aX,TUint32* aScanlinePtr) const
sl@0
   836
	{
sl@0
   837
	// returns pixel as EGray256 value (0 - 255)
sl@0
   838
sl@0
   839
	if (iHeader.iColor)
sl@0
   840
		return TUint8(GetRgbPixelEx(aX,aScanlinePtr)._Gray256());
sl@0
   841
	else
sl@0
   842
		{
sl@0
   843
		if (!aScanlinePtr)
sl@0
   844
			return 0;
sl@0
   845
sl@0
   846
		if (aX >= iHeader.iSizeInPixels.iWidth)
sl@0
   847
			aX %= iHeader.iSizeInPixels.iWidth;
sl@0
   848
sl@0
   849
		switch (iHeader.iBitsPerPixel)
sl@0
   850
			{
sl@0
   851
			case 2:
sl@0
   852
				{
sl@0
   853
				TUint32 col = *(aScanlinePtr+(aX>>4));
sl@0
   854
				col>>=((aX&0xf)<<1);
sl@0
   855
				col&=3;
sl@0
   856
				col |= (col << 6) | (col<<4) | (col<<2);
sl@0
   857
				return TUint8(col);
sl@0
   858
				}
sl@0
   859
			case 4:
sl@0
   860
				{
sl@0
   861
				TUint32 col = *(aScanlinePtr+(aX>>3));
sl@0
   862
				col >>= ((aX&7)<<2);
sl@0
   863
				col &= 0xf;
sl@0
   864
				return TUint8(col |= (col << 4));
sl@0
   865
				}
sl@0
   866
			case 1:
sl@0
   867
				{
sl@0
   868
				TUint32 col = *(aScanlinePtr+(aX>>5));
sl@0
   869
				if (col&(1<<(aX&0x1f))) return 255 ;
sl@0
   870
				return 0;
sl@0
   871
				}
sl@0
   872
			case 8:
sl@0
   873
				return *(((TUint8*)aScanlinePtr) + aX);
sl@0
   874
			default:
sl@0
   875
				return 0;
sl@0
   876
			 }
sl@0
   877
sl@0
   878
		}
sl@0
   879
	}
sl@0
   880
sl@0
   881
TRgb CBitwiseBitmap::GetRgbPixelEx(TInt aX,TUint32* aScanlinePtr) const
sl@0
   882
	{
sl@0
   883
	// returns pixel as TRgb
sl@0
   884
sl@0
   885
	if (iHeader.iColor)
sl@0
   886
		{
sl@0
   887
		if (!aScanlinePtr)
sl@0
   888
			return KRgbBlack;
sl@0
   889
sl@0
   890
		if (aX>=iHeader.iSizeInPixels.iWidth)
sl@0
   891
			aX%=iHeader.iSizeInPixels.iWidth;
sl@0
   892
sl@0
   893
		switch (iHeader.iBitsPerPixel)
sl@0
   894
			{
sl@0
   895
			case 32:
sl@0
   896
				if (iSettings.CurrentDisplayMode() == EColor16MAP)
sl@0
   897
					return TRgb::_Color16MAP(*(aScanlinePtr + aX));
sl@0
   898
				else if (iSettings.CurrentDisplayMode() == EColor16MA)
sl@0
   899
					return TRgb::_Color16MA(*(aScanlinePtr + aX));
sl@0
   900
				//scanLineBytePointer format: BGR0 - 0RGB as INT32.
sl@0
   901
				else
sl@0
   902
					return TRgb::_Color16MU(*(aScanlinePtr + aX));
sl@0
   903
			case 24:
sl@0
   904
				{
sl@0
   905
				TUint8* scanLineBytePointer = (TUint8*)aScanlinePtr + aX * 3;
sl@0
   906
				TInt color16M = *scanLineBytePointer++;
sl@0
   907
				color16M |= (*scanLineBytePointer++) << 8;
sl@0
   908
				color16M |= (*scanLineBytePointer++) << 16;
sl@0
   909
				return TRgb::_Color16M(color16M);
sl@0
   910
				}
sl@0
   911
			case 16:
sl@0
   912
				return TRgb::_Color64K(*(((TUint16*)aScanlinePtr) + aX));
sl@0
   913
			case 12:
sl@0
   914
				return TRgb::_Color4K(*(((TUint16*)aScanlinePtr) + aX));
sl@0
   915
			case 8:
sl@0
   916
				return TRgb::Color256(*((TUint8*)aScanlinePtr + aX));
sl@0
   917
			case 4:
sl@0
   918
				{
sl@0
   919
				TUint8 colorIndex = *((TUint8*)aScanlinePtr + (aX >> 1));
sl@0
   920
				if (aX & 1)
sl@0
   921
					colorIndex >>= 4;
sl@0
   922
				return TRgb::Color16(colorIndex & 0xf);
sl@0
   923
				}
sl@0
   924
			default:
sl@0
   925
				return KRgbBlack;
sl@0
   926
			}
sl@0
   927
		}
sl@0
   928
	else
sl@0
   929
		return TRgb::_Gray256(GetGrayPixelEx(aX,aScanlinePtr));
sl@0
   930
	}
sl@0
   931
sl@0
   932
void CBitwiseBitmap::GetRgbPixelExMany(TInt aX,TUint32* aScanlinePtr, TUint32* aDest,TInt aLength) const
sl@0
   933
    {
sl@0
   934
    __ASSERT_DEBUG(aScanlinePtr && aDest, User::Invariant());
sl@0
   935
    __ASSERT_DEBUG(aX      >= 0, User::Invariant());
sl@0
   936
    __ASSERT_DEBUG(aLength >= 0, User::Invariant());
sl@0
   937
    __ASSERT_DEBUG(aX+aLength <= iHeader.iSizeInPixels.iWidth, User::Invariant());
sl@0
   938
sl@0
   939
    union {
sl@0
   940
        TUint8*  scanPtr8;
sl@0
   941
        TUint16* scanPtr16;
sl@0
   942
        TUint32* scanPtr32;
sl@0
   943
    };
sl@0
   944
    TUint32 color;
sl@0
   945
    TUint32 rawData;
sl@0
   946
    const TUint32 opaqueAlpha = 0xff000000;
sl@0
   947
    TUint32 color16MA = 0;  // // cached map to color
sl@0
   948
sl@0
   949
    if (aLength < 1)
sl@0
   950
        {
sl@0
   951
        return;
sl@0
   952
        }
sl@0
   953
sl@0
   954
    if (iHeader.iColor)
sl@0
   955
        {
sl@0
   956
        switch (iHeader.iBitsPerPixel)
sl@0
   957
            {
sl@0
   958
            case 4:
sl@0
   959
                {
sl@0
   960
                scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr);
sl@0
   961
                TUint32 color16 = EFirstTime; // map source color: 16 color mode
sl@0
   962
                do
sl@0
   963
                    {
sl@0
   964
                    rawData = (aX & 1) ? (scanPtr8[aX >> 1] >> 4) : (scanPtr8[aX >> 1] &0x0F);
sl@0
   965
                    if ((rawData != color16))
sl@0
   966
                        { // first pixel or colour change
sl@0
   967
                        color16MA = TRgb::Color16(rawData)._Color16MA();
sl@0
   968
                        color16 = rawData;
sl@0
   969
                        }
sl@0
   970
                    *aDest++ = color16MA;
sl@0
   971
                    aX++;
sl@0
   972
                    }
sl@0
   973
                    while (--aLength);
sl@0
   974
                return;
sl@0
   975
                }
sl@0
   976
            case 8:
sl@0
   977
                {
sl@0
   978
                scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
sl@0
   979
                const TUint32* lookup = DynamicPalette::DefaultColor256Util()->iColorTable;
sl@0
   980
                TUint32 color256 = EFirstTime; // map source color: 256 color
sl@0
   981
                do
sl@0
   982
                    {
sl@0
   983
                    rawData = *scanPtr8++;
sl@0
   984
                    if ((rawData != color256))
sl@0
   985
                        { // colour change or first pixel
sl@0
   986
                        color16MA = lookup[rawData];
sl@0
   987
                        color256 = rawData;
sl@0
   988
                        // translate between bgr & rgb
sl@0
   989
                        color16MA = ((color16MA & 0x0000ff) << 16) | (color16MA & 0x00ff00) | ((color16MA & 0xff0000) >> 16) | opaqueAlpha;
sl@0
   990
                        }
sl@0
   991
                    *aDest++ = color16MA;
sl@0
   992
                    }
sl@0
   993
                    while (--aLength);
sl@0
   994
                return;
sl@0
   995
                }
sl@0
   996
            case 12:
sl@0
   997
                {
sl@0
   998
                scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
sl@0
   999
                TUint32 color4K = EFirstTime; // map source color: 4K color black => 16M color black
sl@0
  1000
                do
sl@0
  1001
                    {
sl@0
  1002
                    rawData = *scanPtr16++;
sl@0
  1003
                    if ((rawData != color4K))
sl@0
  1004
                        { // colour change
sl@0
  1005
                        color16MA = TRgb::_Color4K(rawData)._Color16MA();
sl@0
  1006
                        color4K = rawData;
sl@0
  1007
                        }
sl@0
  1008
                    *aDest++ = color16MA;
sl@0
  1009
                    }
sl@0
  1010
                    while (--aLength);
sl@0
  1011
                return;
sl@0
  1012
                }
sl@0
  1013
            case 16:
sl@0
  1014
                {
sl@0
  1015
                scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
sl@0
  1016
                const TUint16* lowAdd = Convert16to32bppLow();
sl@0
  1017
                const TUint32* highAdd = Convert16to32bppHigh();
sl@0
  1018
                TUint32 color64K = EFirstTime; // map source color: 64K color black => 16M color black
sl@0
  1019
                do
sl@0
  1020
                    {
sl@0
  1021
                    rawData = *scanPtr16++;
sl@0
  1022
                    if ((rawData != color64K))
sl@0
  1023
                        { // colour change
sl@0
  1024
                        color16MA = highAdd[rawData >> 8] | lowAdd[rawData & 0x00FF];
sl@0
  1025
                        color64K = rawData;
sl@0
  1026
                        }
sl@0
  1027
                    *aDest++ = color16MA;
sl@0
  1028
                    }
sl@0
  1029
                    while (--aLength);
sl@0
  1030
                return;
sl@0
  1031
                }
sl@0
  1032
            case 24:
sl@0
  1033
                {
sl@0
  1034
                scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX*3;
sl@0
  1035
                do
sl@0
  1036
                    {
sl@0
  1037
                    if ((aLength < 4) || (3 & (TUint32)(scanPtr8)))
sl@0
  1038
                        {
sl@0
  1039
                        aLength--;
sl@0
  1040
                        color  =  *scanPtr8++;
sl@0
  1041
                        color |= (*scanPtr8++) << 8;
sl@0
  1042
                        color |= (*scanPtr8++) << 16;
sl@0
  1043
                        *aDest++ = color | opaqueAlpha;
sl@0
  1044
                        }
sl@0
  1045
                    else
sl@0
  1046
                        { // source is now TUint32 aligned - so read source as blocks of 3 TUint32's & write as 4
sl@0
  1047
                        TUint32 word1, word2, word3;
sl@0
  1048
                        TInt iter = (aLength / 4) - 1;
sl@0
  1049
                        aLength = aLength & 0x0003;
sl@0
  1050
                        do
sl@0
  1051
                            {
sl@0
  1052
                            word1 = *scanPtr32++; 
sl@0
  1053
                            *aDest++ = word1 | opaqueAlpha;
sl@0
  1054
                            word2 = *scanPtr32++; 
sl@0
  1055
                            color = (word1 >> 24) | ((word2 & 0xFFFF) << 8); 
sl@0
  1056
                            *aDest++ = color | opaqueAlpha;
sl@0
  1057
                            word3 = *scanPtr32++; 
sl@0
  1058
                            color = (word2 >> 16) | ((word3 & 0x00FF) << 16); 
sl@0
  1059
                            *aDest++ = color | opaqueAlpha;
sl@0
  1060
                            *aDest++ = (word3 >> 8) | opaqueAlpha;
sl@0
  1061
                            }
sl@0
  1062
                            while (iter--);
sl@0
  1063
                        }
sl@0
  1064
                    }
sl@0
  1065
                    while (aLength);
sl@0
  1066
                return;
sl@0
  1067
                }
sl@0
  1068
            case 32:
sl@0
  1069
                {
sl@0
  1070
                scanPtr32 = aScanlinePtr + aX;
sl@0
  1071
                if(iSettings.CurrentDisplayMode() == EColor16MAP)
sl@0
  1072
                    { // unrolled loop uses "Duff's Device"
sl@0
  1073
                    const TUint16* normTable = PtrTo16BitNormalisationTable();
sl@0
  1074
                    --aLength;
sl@0
  1075
                    TInt iter = aLength / 8;
sl@0
  1076
                    switch(aLength & 7) 
sl@0
  1077
                        {
sl@0
  1078
                        case 7:
sl@0
  1079
                            do {
sl@0
  1080
                                *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1081
                        case 6:
sl@0
  1082
                                *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1083
                        case 5:
sl@0
  1084
                                *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1085
                        case 4:
sl@0
  1086
                                *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1087
                        case 3:
sl@0
  1088
                                *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1089
                        case 2:
sl@0
  1090
                                *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1091
                        case 1:
sl@0
  1092
                                *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1093
                        case 0:
sl@0
  1094
                                *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1095
                            } while (iter-- > 0);
sl@0
  1096
                        }
sl@0
  1097
                    }
sl@0
  1098
                else if (iSettings.CurrentDisplayMode() == EColor16MU)
sl@0
  1099
                    { // unrolled loop uses "Duff's Device"
sl@0
  1100
                    --aLength;
sl@0
  1101
                    TInt iter = aLength / 8;
sl@0
  1102
                    switch(aLength & 7) 
sl@0
  1103
                        {
sl@0
  1104
                        case 7:
sl@0
  1105
                            do {
sl@0
  1106
                                *aDest++ = (*scanPtr32++) | opaqueAlpha;
sl@0
  1107
                        case 6:
sl@0
  1108
                                *aDest++ = (*scanPtr32++) | opaqueAlpha;
sl@0
  1109
                        case 5:
sl@0
  1110
                                *aDest++ = (*scanPtr32++) | opaqueAlpha;
sl@0
  1111
                        case 4:
sl@0
  1112
                                *aDest++ = (*scanPtr32++) | opaqueAlpha;
sl@0
  1113
                        case 3:
sl@0
  1114
                                *aDest++ = (*scanPtr32++) | opaqueAlpha;
sl@0
  1115
                        case 2:
sl@0
  1116
                                *aDest++ = (*scanPtr32++) | opaqueAlpha;
sl@0
  1117
                        case 1:
sl@0
  1118
                                *aDest++ = (*scanPtr32++) | opaqueAlpha;
sl@0
  1119
                        case 0:
sl@0
  1120
                                *aDest++ = (*scanPtr32++) | opaqueAlpha;
sl@0
  1121
                            } while (iter-- > 0);
sl@0
  1122
                        }
sl@0
  1123
                    }
sl@0
  1124
                else // EColor16MA
sl@0
  1125
                    {
sl@0
  1126
                    Mem::Move(aDest, scanPtr32, aLength * 4);
sl@0
  1127
                    }
sl@0
  1128
                return;
sl@0
  1129
                }
sl@0
  1130
            default:
sl@0
  1131
                return;
sl@0
  1132
            }
sl@0
  1133
        }
sl@0
  1134
    else
sl@0
  1135
        {
sl@0
  1136
        switch (iHeader.iBitsPerPixel)
sl@0
  1137
            {
sl@0
  1138
            case 1:
sl@0
  1139
                {
sl@0
  1140
                do
sl@0
  1141
                    {
sl@0
  1142
                    *aDest++ = TUint32(COLOR_VALUE(aScanlinePtr, aX) ? 0xFFFFFFFF : 0xFF000000);
sl@0
  1143
                    aX++;
sl@0
  1144
                    }
sl@0
  1145
                while (--aLength);
sl@0
  1146
                break;
sl@0
  1147
                }
sl@0
  1148
            case 8:
sl@0
  1149
                {
sl@0
  1150
                scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
sl@0
  1151
                do
sl@0
  1152
                    {
sl@0
  1153
                    rawData = *scanPtr8++;
sl@0
  1154
                    color16MA = rawData | (rawData << 8) | (rawData << 16) | opaqueAlpha; 
sl@0
  1155
                    *aDest++ = color16MA;
sl@0
  1156
                    }
sl@0
  1157
                    while (--aLength);              
sl@0
  1158
                break;
sl@0
  1159
                }
sl@0
  1160
            default:
sl@0
  1161
                {
sl@0
  1162
                do
sl@0
  1163
                    {
sl@0
  1164
                    rawData = GetGrayPixelEx(aX++,aScanlinePtr);
sl@0
  1165
                    color16MA = rawData | (rawData << 8) | (rawData << 16) | opaqueAlpha; 
sl@0
  1166
                    *aDest++ = color16MA;
sl@0
  1167
                    }
sl@0
  1168
                    while (--aLength);              
sl@0
  1169
                }
sl@0
  1170
            }
sl@0
  1171
        }
sl@0
  1172
    }
sl@0
  1173
/**
sl@0
  1174
The method retrieves the RGB color values from the scanline, and converts them
sl@0
  1175
into the destination screen-mode pixel format. This method handles the special
sl@0
  1176
case when the destination mode is EColor16MAP (32bit with alpha values premultiplied
sl@0
  1177
with the color channels. Calls GetRgbPixelExMany for values not 32 bit, as there is no
sl@0
  1178
alpha information in these color modes. For color mode EColor16MU, no conversion is 
sl@0
  1179
performed (as alpha is assumed to be 1).
sl@0
  1180
@internalComponent
sl@0
  1181
@released
sl@0
  1182
@param aX	The x co-ordinate the scanline data needs to be retrieved from.
sl@0
  1183
@param aScanlinePtr	The scanline pointer, i.e. the source data.
sl@0
  1184
@param aDest	The pointer to the destination buffer. This is where the output is stored.
sl@0
  1185
@param aLength	The number of bytes to be copied. This value must be a multiple of 4.
sl@0
  1186
*/
sl@0
  1187
void CBitwiseBitmap::GetRgbPixelExMany16MAP(TInt aX,TUint32* aScanlinePtr,TUint32* aDest,TInt aLength) const
sl@0
  1188
    {
sl@0
  1189
    __ASSERT_DEBUG(aScanlinePtr && aDest, User::Invariant());
sl@0
  1190
    __ASSERT_DEBUG(aX      >= 0, User::Invariant());
sl@0
  1191
    __ASSERT_DEBUG(aLength >= 0, User::Invariant());
sl@0
  1192
    __ASSERT_DEBUG(aX+aLength <= iHeader.iSizeInPixels.iWidth, User::Invariant());
sl@0
  1193
sl@0
  1194
    TUint32* scanPtr32;
sl@0
  1195
sl@0
  1196
    if ((iHeader.iColor) && (iHeader.iBitsPerPixel == 32))
sl@0
  1197
        {
sl@0
  1198
        scanPtr32 = aScanlinePtr + aX;
sl@0
  1199
        if (DisplayMode() == EColor16MAP)
sl@0
  1200
            {
sl@0
  1201
            Mem::Move(aDest, scanPtr32, aLength<<2);
sl@0
  1202
            }
sl@0
  1203
        else if(DisplayMode()==EColor16MA)
sl@0
  1204
            {
sl@0
  1205
            TUint32* ptrLimit = aDest + aLength;
sl@0
  1206
            const TInt32 zero = 0;
sl@0
  1207
            while (aDest < ptrLimit)
sl@0
  1208
                {
sl@0
  1209
                TUint32 value = *scanPtr32++;
sl@0
  1210
                TUint32 tA = value >> 24;
sl@0
  1211
                if (tA == 0)
sl@0
  1212
                    {
sl@0
  1213
                    *aDest++ = zero;
sl@0
  1214
                    }
sl@0
  1215
                else if (tA != 255) 
sl@0
  1216
                    {
sl@0
  1217
                    *aDest++ = NonPMA2PMAPixel(value);
sl@0
  1218
                    }
sl@0
  1219
                else
sl@0
  1220
                    {
sl@0
  1221
                    *aDest++ = value;
sl@0
  1222
                    }
sl@0
  1223
                }
sl@0
  1224
            }
sl@0
  1225
        else // DisplayMode() == EColor16MU
sl@0
  1226
            {
sl@0
  1227
            if (aLength--)
sl@0
  1228
                { // unrolled loop uses "Duff's Device"
sl@0
  1229
                const TUint32 alpha = 0xFF000000;   //set all the alpha to 0xff
sl@0
  1230
                TInt iter = aLength / 8;
sl@0
  1231
                switch(aLength & 7) 
sl@0
  1232
                    {
sl@0
  1233
                    case 7:
sl@0
  1234
                        do {
sl@0
  1235
                            *aDest++ = (*scanPtr32++) | alpha;
sl@0
  1236
                    case 6:
sl@0
  1237
                            *aDest++ = (*scanPtr32++) | alpha;
sl@0
  1238
                    case 5:
sl@0
  1239
                            *aDest++ = (*scanPtr32++) | alpha;
sl@0
  1240
                    case 4:
sl@0
  1241
                            *aDest++ = (*scanPtr32++) | alpha;
sl@0
  1242
                    case 3:
sl@0
  1243
                            *aDest++ = (*scanPtr32++) | alpha;
sl@0
  1244
                    case 2:
sl@0
  1245
                            *aDest++ = (*scanPtr32++) | alpha;
sl@0
  1246
                    case 1:
sl@0
  1247
                            *aDest++ = (*scanPtr32++) | alpha;
sl@0
  1248
                    case 0:
sl@0
  1249
                            *aDest++ = (*scanPtr32++) | alpha;
sl@0
  1250
                        } while (iter-- > 0);
sl@0
  1251
                    }
sl@0
  1252
                }
sl@0
  1253
            }
sl@0
  1254
        }
sl@0
  1255
    else
sl@0
  1256
        {
sl@0
  1257
        GetRgbPixelExMany(aX, aScanlinePtr, aDest, aLength);
sl@0
  1258
        }
sl@0
  1259
    }
sl@0
  1260
sl@0
  1261
void CBitwiseBitmap::GetRgbPixelExMany16M(TInt aX,TUint32* aScanlinePtr, TUint8* aDest,TInt aLength) const
sl@0
  1262
    {
sl@0
  1263
    union {
sl@0
  1264
        TUint8*  scanPtr8;
sl@0
  1265
        TUint16* scanPtr16;
sl@0
  1266
        TUint32* scanPtr32;
sl@0
  1267
    };
sl@0
  1268
    union {
sl@0
  1269
        TUint8*  destPtr8;
sl@0
  1270
        TUint32* destPtr32;
sl@0
  1271
    };
sl@0
  1272
    destPtr8 = aDest;
sl@0
  1273
    TUint32 rawData;
sl@0
  1274
sl@0
  1275
    if (!aScanlinePtr)
sl@0
  1276
        {
sl@0
  1277
        const TUint32 zero = 0; // conveniently KRgbBlack is 0 in EColor16M mode
sl@0
  1278
        while (aLength)
sl@0
  1279
            {
sl@0
  1280
            if ((aLength < 4) || (3 & (TUint32)(destPtr8)))
sl@0
  1281
                {
sl@0
  1282
                aLength--;
sl@0
  1283
                *destPtr8++ = zero;
sl@0
  1284
                *destPtr8++ = zero;
sl@0
  1285
                *destPtr8++ = zero;
sl@0
  1286
                }
sl@0
  1287
            else
sl@0
  1288
                { // dest is now TUint32 aligned - write 4 pixels into 3 TUint32s
sl@0
  1289
                aLength -= 4;
sl@0
  1290
                *destPtr32++ = zero;
sl@0
  1291
                *destPtr32++ = zero;
sl@0
  1292
                *destPtr32++ = zero;
sl@0
  1293
                }
sl@0
  1294
            }
sl@0
  1295
        return;
sl@0
  1296
        }
sl@0
  1297
sl@0
  1298
    if (aX>=iHeader.iSizeInPixels.iWidth)
sl@0
  1299
        {
sl@0
  1300
        aX%=iHeader.iSizeInPixels.iWidth;
sl@0
  1301
        }
sl@0
  1302
sl@0
  1303
    while (aLength)
sl@0
  1304
        {
sl@0
  1305
        // cached map to color
sl@0
  1306
        TUint32 color16M = 0;
sl@0
  1307
        TInt copyLength = iHeader.iSizeInPixels.iWidth - aX;
sl@0
  1308
        TUint32* scanPtr32 = aScanlinePtr + aX;
sl@0
  1309
        if (copyLength > aLength)
sl@0
  1310
            {
sl@0
  1311
            copyLength = aLength;
sl@0
  1312
            }
sl@0
  1313
        aLength -= copyLength;
sl@0
  1314
sl@0
  1315
        if (iHeader.iColor)
sl@0
  1316
            {
sl@0
  1317
            switch(iHeader.iBitsPerPixel)
sl@0
  1318
                {
sl@0
  1319
                case 4:
sl@0
  1320
                    {
sl@0
  1321
                    scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr);
sl@0
  1322
                    TUint32 color16 = EFirstTime; // map source color: 16 color mode
sl@0
  1323
                    do
sl@0
  1324
                        {
sl@0
  1325
                        rawData = (aX & 1) ? (scanPtr8[aX >> 1] >> 4) : (scanPtr8[aX >> 1] &0x0F);
sl@0
  1326
                        if ((rawData != color16))
sl@0
  1327
                            { // first pixel or colour change
sl@0
  1328
                            color16M = TRgb::Color16(rawData)._Color16M();
sl@0
  1329
                            color16 = rawData;
sl@0
  1330
                            }
sl@0
  1331
                        *destPtr8++ = TUint8(color16M);
sl@0
  1332
                        *destPtr8++ = TUint8(color16M >> 8);
sl@0
  1333
                        *destPtr8++ = TUint8(color16M >> 16);
sl@0
  1334
                        aX++;
sl@0
  1335
                        }
sl@0
  1336
                        while (--copyLength);
sl@0
  1337
                    break;
sl@0
  1338
                    }
sl@0
  1339
                case 8:
sl@0
  1340
                    {
sl@0
  1341
                    scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
sl@0
  1342
                    const TUint32* lookup = DynamicPalette::DefaultColor256Util()->iColorTable;
sl@0
  1343
                    TUint32 color256 = EFirstTime; // map source color: 256 color
sl@0
  1344
                    do
sl@0
  1345
                        {
sl@0
  1346
                        rawData = *scanPtr8++;
sl@0
  1347
                        if ((rawData != color256))
sl@0
  1348
                            { // first pixel or colour change; so perform new mapping
sl@0
  1349
                            color16M = lookup[rawData];
sl@0
  1350
                            color256 = rawData;
sl@0
  1351
                            }
sl@0
  1352
                        // Note; byte order performs required bgr -> rgb conversion 
sl@0
  1353
                        *destPtr8++ = TUint8(color16M >> 16);
sl@0
  1354
                        *destPtr8++ = TUint8(color16M >> 8);
sl@0
  1355
                        *destPtr8++ = TUint8(color16M);
sl@0
  1356
                        }
sl@0
  1357
                        while (--copyLength);
sl@0
  1358
                    break;
sl@0
  1359
                    }
sl@0
  1360
                case 12:
sl@0
  1361
                    {
sl@0
  1362
                    scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
sl@0
  1363
                    TUint32 color4K = EFirstTime; // map source color: 4K color black => 16M color black
sl@0
  1364
                    do
sl@0
  1365
                        {
sl@0
  1366
                        rawData = *scanPtr16++;
sl@0
  1367
                        if ((rawData != color4K))
sl@0
  1368
                            { // first pixel or colour change
sl@0
  1369
                            color16M = TRgb::_Color4K(rawData)._Color16M();
sl@0
  1370
                            color4K = rawData;
sl@0
  1371
                            }
sl@0
  1372
                        *destPtr8++ = TUint8(color16M);
sl@0
  1373
                        *destPtr8++ = TUint8(color16M >> 8);
sl@0
  1374
                        *destPtr8++ = TUint8(color16M >> 16);
sl@0
  1375
                        }
sl@0
  1376
                        while (--copyLength);
sl@0
  1377
                    break;
sl@0
  1378
                    }
sl@0
  1379
                case 16:
sl@0
  1380
                    {
sl@0
  1381
                    scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
sl@0
  1382
                    const TUint16* lowAdd = Convert16to32bppLow();
sl@0
  1383
                    const TUint32* highAdd = Convert16to32bppHigh();
sl@0
  1384
                    TUint16 halfWord;
sl@0
  1385
                    TUint32 color64K = EFirstTime; // 64K color black => 16M color black
sl@0
  1386
                    color16M = 0;
sl@0
  1387
                    do
sl@0
  1388
                        {
sl@0
  1389
                        halfWord = *scanPtr16++;
sl@0
  1390
                        if ((halfWord != color64K))
sl@0
  1391
                            { // colour change
sl@0
  1392
                            color16M = highAdd[halfWord >> 8] | lowAdd[halfWord & 0x00FF];
sl@0
  1393
                            color64K = halfWord;
sl@0
  1394
                            }
sl@0
  1395
                        *destPtr8++ = TUint8(color16M);
sl@0
  1396
                        *destPtr8++ = TUint8(color16M >> 8);
sl@0
  1397
                        *destPtr8++ = TUint8(color16M >> 16);
sl@0
  1398
                        }
sl@0
  1399
                        while (--copyLength);
sl@0
  1400
                    break;
sl@0
  1401
                    }
sl@0
  1402
                case 24:
sl@0
  1403
                    {
sl@0
  1404
                    Mem::Copy(destPtr8, reinterpret_cast<TUint8*>(aScanlinePtr) + aX, copyLength * 3); // may not be aligned 
sl@0
  1405
                    destPtr8 += copyLength * 3;
sl@0
  1406
                    break;
sl@0
  1407
                    }
sl@0
  1408
                case 32:
sl@0
  1409
                    {
sl@0
  1410
                    scanPtr32 = aScanlinePtr + aX;
sl@0
  1411
                    if (iSettings.CurrentDisplayMode() == EColor16MAP)
sl@0
  1412
                        {
sl@0
  1413
                        const TUint16* normTable = PtrTo16BitNormalisationTable();
sl@0
  1414
                        do
sl@0
  1415
                            {
sl@0
  1416
                            // convert from EColor16MAP to EColor16MA first.
sl@0
  1417
                            color16M = PMA2NonPMAPixel(*scanPtr32++, normTable);
sl@0
  1418
                            *destPtr8++ = TUint8(color16M);
sl@0
  1419
                            *destPtr8++ = TUint8(color16M >> 8);
sl@0
  1420
                            *destPtr8++ = TUint8(color16M >> 16);
sl@0
  1421
                            }
sl@0
  1422
                            while (--copyLength);
sl@0
  1423
                        }
sl@0
  1424
                    else
sl@0
  1425
                        { // EColor16MA or EColor16MU, keep the RGB & throw away the top byte
sl@0
  1426
                        // scanLineBytePointer format: ARGB - 0RGB as INT32 or BGR0 - 0RGB as INT32.
sl@0
  1427
                        do
sl@0
  1428
                            {
sl@0
  1429
                            if ((copyLength < 4) || (3 & (TUint32)destPtr8))
sl@0
  1430
                                {
sl@0
  1431
                                color16M = *scanPtr32++;
sl@0
  1432
                                --copyLength;
sl@0
  1433
                                *destPtr8++ = TUint8(color16M);
sl@0
  1434
                                *destPtr8++ = TUint8(color16M >> 8);
sl@0
  1435
                                *destPtr8++ = TUint8(color16M >> 16);
sl@0
  1436
                                }
sl@0
  1437
                            else // dest is TUint32 aligned: copy 4 pixels into 3 TUint32's
sl@0
  1438
                                {
sl@0
  1439
                                color16M = (*scanPtr32++) & 0x00FFFFFF;
sl@0
  1440
                                rawData = (*scanPtr32++) & 0x00FFFFFF;
sl@0
  1441
                                copyLength -= 4;
sl@0
  1442
                                *destPtr32++ = color16M | (rawData << 24);
sl@0
  1443
                                color16M = (*scanPtr32++) & 0x00FFFFFF;
sl@0
  1444
                                *destPtr32++ = (color16M << 16) | (rawData >> 8);
sl@0
  1445
                                rawData = (*scanPtr32++) & 0x00FFFFFF;
sl@0
  1446
                                *destPtr32++ = (color16M >> 16) | (rawData << 8);
sl@0
  1447
                                }
sl@0
  1448
                            }
sl@0
  1449
                            while (copyLength);
sl@0
  1450
                        }
sl@0
  1451
                    break;
sl@0
  1452
                    }
sl@0
  1453
                default:
sl@0
  1454
                    break;
sl@0
  1455
                }
sl@0
  1456
            }
sl@0
  1457
        else
sl@0
  1458
            { // !iHeader.iColor
sl@0
  1459
            if (iHeader.iBitsPerPixel == 8)
sl@0
  1460
                {
sl@0
  1461
                scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
sl@0
  1462
                do
sl@0
  1463
                    {
sl@0
  1464
                    rawData = *scanPtr8++;
sl@0
  1465
                    *destPtr8++ = (TUint8)rawData;
sl@0
  1466
                    *destPtr8++ = (TUint8)rawData;
sl@0
  1467
                    *destPtr8++ = (TUint8)rawData;
sl@0
  1468
                    }
sl@0
  1469
                    while (--copyLength);
sl@0
  1470
                }
sl@0
  1471
            else
sl@0
  1472
                {
sl@0
  1473
                do
sl@0
  1474
                    {
sl@0
  1475
                    rawData = GetGrayPixelEx(aX++,aScanlinePtr);
sl@0
  1476
                    *destPtr8++ = (TUint8)rawData;
sl@0
  1477
                    *destPtr8++ = (TUint8)rawData;
sl@0
  1478
                    *destPtr8++ = (TUint8)rawData;
sl@0
  1479
                    }
sl@0
  1480
                    while (--copyLength);
sl@0
  1481
                }
sl@0
  1482
            }
sl@0
  1483
        aX = 0; // second copy, if any, comes from start of line
sl@0
  1484
        }
sl@0
  1485
sl@0
  1486
    return;
sl@0
  1487
    }
sl@0
  1488
sl@0
  1489
void CBitwiseBitmap::GenerateLineFromCompressedEightBitData(TUint8* aDestBuffer, const TPoint& aPixel,TInt aLength, TUint32* aBase,TLineScanningPosition& aLineScanningPosition) const
sl@0
  1490
	{
sl@0
  1491
	const TInt bitmapWidth=iByteWidth;
sl@0
  1492
	const TInt pixelsPerByte=8/iHeader.iBitsPerPixel;
sl@0
  1493
	const TInt startPos=aPixel.iY*bitmapWidth+aPixel.iX/pixelsPerByte;
sl@0
  1494
	const TInt endPos=aPixel.iY*bitmapWidth+(aPixel.iX+aLength+pixelsPerByte-1)/pixelsPerByte;
sl@0
  1495
	const TInt byteLength=endPos-startPos;
sl@0
  1496
	TInt writes=byteLength;
sl@0
  1497
	TUint8* destPtr = ((TUint8*)aDestBuffer);
sl@0
  1498
	destPtr+=(aPixel.iX/pixelsPerByte);
sl@0
  1499
	if (aLineScanningPosition.iCursorPos>startPos)
sl@0
  1500
		{
sl@0
  1501
		aLineScanningPosition.iSrcDataPtr=(TUint8*)aBase;
sl@0
  1502
		aLineScanningPosition.iCursorPos=0;
sl@0
  1503
		}
sl@0
  1504
	TUint8* srcePtr = (TUint8*)aLineScanningPosition.iSrcDataPtr;
sl@0
  1505
	TInt8 count=*srcePtr;
sl@0
  1506
	TInt16 addition;
sl@0
  1507
	if (count<0)
sl@0
  1508
		addition=(TInt16) (-count);
sl@0
  1509
	else
sl@0
  1510
		addition=(TInt16) (count+1);
sl@0
  1511
	while (aLineScanningPosition.iCursorPos+addition<startPos)
sl@0
  1512
		{
sl@0
  1513
		aLineScanningPosition.iCursorPos+=addition;
sl@0
  1514
		if (count<0)
sl@0
  1515
			{
sl@0
  1516
			srcePtr+=(-count+1);
sl@0
  1517
			}
sl@0
  1518
		else
sl@0
  1519
			{
sl@0
  1520
			srcePtr+=2;  // Just skip over value
sl@0
  1521
			}
sl@0
  1522
		count = *srcePtr;
sl@0
  1523
		if (count<0)
sl@0
  1524
			addition=(TInt16) (-count);
sl@0
  1525
		else
sl@0
  1526
			addition=(TInt16) (count+1);
sl@0
  1527
		}
sl@0
  1528
	// Then scan the line
sl@0
  1529
	count=0;
sl@0
  1530
	while (aLineScanningPosition.iCursorPos+count<startPos+byteLength)
sl@0
  1531
		{
sl@0
  1532
		TBool negativeCount=EFalse;
sl@0
  1533
		count=*srcePtr;
sl@0
  1534
		if (count<0)
sl@0
  1535
			{
sl@0
  1536
			negativeCount=ETrue;
sl@0
  1537
			count=(TInt8) ((-count)-1);
sl@0
  1538
			}
sl@0
  1539
		TUint8 value = *(srcePtr+1);
sl@0
  1540
		TInt distanceToTheLineEnd=startPos+byteLength-aLineScanningPosition.iCursorPos;
sl@0
  1541
		if (count<distanceToTheLineEnd)
sl@0
  1542
			{
sl@0
  1543
			if (!negativeCount)
sl@0
  1544
				{
sl@0
  1545
				srcePtr+=2;
sl@0
  1546
				}
sl@0
  1547
			else
sl@0
  1548
				{
sl@0
  1549
				srcePtr+=1;
sl@0
  1550
				}
sl@0
  1551
			TInt countPlusOne = (TInt)count + 1;
sl@0
  1552
			TInt start = Max(0,startPos-aLineScanningPosition.iCursorPos);
sl@0
  1553
			if (countPlusOne > start)
sl@0
  1554
				{
sl@0
  1555
				TInt length = Min(countPlusOne-start,writes);
sl@0
  1556
				writes -= countPlusOne-start;
sl@0
  1557
				if (length > 0)
sl@0
  1558
					{
sl@0
  1559
					/*Mem::Fill and Mem::Copy used in order to increase the performance*/
sl@0
  1560
					if (!negativeCount)
sl@0
  1561
						{
sl@0
  1562
						Mem::Fill(destPtr,length,value);
sl@0
  1563
						}
sl@0
  1564
					else
sl@0
  1565
						{
sl@0
  1566
						Mem::Copy(destPtr,srcePtr+start,length);
sl@0
  1567
						}
sl@0
  1568
					destPtr += length;
sl@0
  1569
					}
sl@0
  1570
				}
sl@0
  1571
			if (negativeCount)
sl@0
  1572
				{
sl@0
  1573
				srcePtr += countPlusOne;
sl@0
  1574
				}
sl@0
  1575
			aLineScanningPosition.iCursorPos += countPlusOne;
sl@0
  1576
			count=0;
sl@0
  1577
			}
sl@0
  1578
			else
sl@0
  1579
			{
sl@0
  1580
			TInt correction=1;
sl@0
  1581
			if (aLineScanningPosition.iCursorPos<startPos)
sl@0
  1582
				{
sl@0
  1583
				correction=startPos-aLineScanningPosition.iCursorPos+1;
sl@0
  1584
				}
sl@0
  1585
			TInt length = Min(byteLength,writes);
sl@0
  1586
			writes -= length;
sl@0
  1587
			/*Mem::Fill and Mem::Copy used in order to increase the performance*/
sl@0
  1588
			if (!negativeCount)
sl@0
  1589
				{
sl@0
  1590
				Mem::Fill(destPtr,length,value);
sl@0
  1591
				}
sl@0
  1592
			else
sl@0
  1593
				{
sl@0
  1594
				Mem::Copy(destPtr,srcePtr+correction,length);
sl@0
  1595
				}
sl@0
  1596
			destPtr += length;
sl@0
  1597
			}
sl@0
  1598
		}
sl@0
  1599
	aLineScanningPosition.iSrcDataPtr=(TUint8*) srcePtr;
sl@0
  1600
	}
sl@0
  1601
sl@0
  1602
void CBitwiseBitmap::GenerateLineFromCompressedTwelveBitData(TUint8* aDestBuffer, const TPoint& aPixel,TInt aLength, TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
sl@0
  1603
	{
sl@0
  1604
	const TInt bitmapWidth=iByteWidth>>1;
sl@0
  1605
	const TInt startPos=aPixel.iY*bitmapWidth+aPixel.iX;
sl@0
  1606
	TInt writes=aLength*2;
sl@0
  1607
	TUint16* destPtr = ((TUint16*)aDestBuffer);//+aPixel.iX;
sl@0
  1608
	destPtr+=aPixel.iX;
sl@0
  1609
sl@0
  1610
	if(iPile)
sl@0
  1611
		{
sl@0
  1612
		::AdjustLineScanningPosition(aLineScanningPosition, aBase, bitmapWidth, startPos, iHeader.iBitmapSize - sizeof(SEpocBitmapHeader));
sl@0
  1613
		}
sl@0
  1614
	TUint16* srcePtr = (TUint16*)aLineScanningPosition.iSrcDataPtr;
sl@0
  1615
sl@0
  1616
	// Fast find the correct position to start
sl@0
  1617
	TInt count=0;
sl@0
  1618
	if(::Abs(aLineScanningPosition.iCursorPos - startPos) > startPos)
sl@0
  1619
		{
sl@0
  1620
		srcePtr = (TUint16*)aBase;
sl@0
  1621
		aLineScanningPosition.iCursorPos = 0;
sl@0
  1622
		}
sl@0
  1623
	while (aLineScanningPosition.iCursorPos>startPos)
sl@0
  1624
		{
sl@0
  1625
		srcePtr--;
sl@0
  1626
		TUint16 value = *srcePtr;
sl@0
  1627
		count = value >> 12;
sl@0
  1628
		aLineScanningPosition.iCursorPos-=(count+1);
sl@0
  1629
		}
sl@0
  1630
	while (aLineScanningPosition.iCursorPos<startPos)
sl@0
  1631
		{
sl@0
  1632
		TUint16 value = *srcePtr++;
sl@0
  1633
		count = value >> 12;
sl@0
  1634
		aLineScanningPosition.iCursorPos+=count+1;
sl@0
  1635
		}
sl@0
  1636
	if (aLineScanningPosition.iCursorPos>startPos)
sl@0
  1637
		{
sl@0
  1638
		aLineScanningPosition.iCursorPos-=(count+1);
sl@0
  1639
		srcePtr--;
sl@0
  1640
		}
sl@0
  1641
sl@0
  1642
	// Then scan the line
sl@0
  1643
	count=0;
sl@0
  1644
	while (aLineScanningPosition.iCursorPos+count<startPos+aLength)
sl@0
  1645
		{
sl@0
  1646
		TUint16 value = *srcePtr;
sl@0
  1647
		count = value >> 12;
sl@0
  1648
		value &= 0x0fff;
sl@0
  1649
		TInt distanceToTheLineEnd=startPos+aLength-aLineScanningPosition.iCursorPos;
sl@0
  1650
		if (count<distanceToTheLineEnd)
sl@0
  1651
			{
sl@0
  1652
			srcePtr++;
sl@0
  1653
			for (TInt ii=0 ; ii<=count ; ii++)
sl@0
  1654
				{
sl@0
  1655
				if (aLineScanningPosition.iCursorPos>=startPos)
sl@0
  1656
					{
sl@0
  1657
					if (writes>0)
sl@0
  1658
						*destPtr++ = value;
sl@0
  1659
					writes-=2;
sl@0
  1660
					}
sl@0
  1661
				aLineScanningPosition.iCursorPos++;
sl@0
  1662
sl@0
  1663
				}
sl@0
  1664
			count=0;
sl@0
  1665
			}
sl@0
  1666
		else
sl@0
  1667
			{
sl@0
  1668
			for (TInt ii=0 ; ii<distanceToTheLineEnd ; ii++)
sl@0
  1669
				{
sl@0
  1670
				writes-=2;
sl@0
  1671
				*destPtr++ = value;
sl@0
  1672
				if (writes==0)
sl@0
  1673
					break;
sl@0
  1674
				}
sl@0
  1675
			}
sl@0
  1676
		}
sl@0
  1677
	aLineScanningPosition.iSrcDataPtr=(TUint8*) srcePtr;
sl@0
  1678
	}
sl@0
  1679
sl@0
  1680
/**
sl@0
  1681
The method generates a line from compressed 16 bpp bitmap data.
sl@0
  1682
@internalComponent
sl@0
  1683
@see TScanLineDecompressor
sl@0
  1684
*/
sl@0
  1685
void CBitwiseBitmap::GenerateLineFromCompressedSixteenBitData(TUint8* aDestBuffer,
sl@0
  1686
															  const TPoint& aPixel,
sl@0
  1687
															  TInt aLength,
sl@0
  1688
															  TUint32* aBase,
sl@0
  1689
															  TLineScanningPosition& aLineScanningPosition) const
sl@0
  1690
	{
sl@0
  1691
	TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
sl@0
  1692
	TScanLineDecompressor<E2bpp, E2bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
sl@0
  1693
	decompr(aDestBuffer, aPixel, aLineScanningPosition, iByteWidth, iByteWidth, aLength);
sl@0
  1694
	}
sl@0
  1695
sl@0
  1696
/**
sl@0
  1697
The method generates a line from compressed 24 bpp bitmap data.
sl@0
  1698
@internalComponent
sl@0
  1699
@see TScanLineDecompressor
sl@0
  1700
*/
sl@0
  1701
void CBitwiseBitmap::GenerateLineFromCompressed24BitData(
sl@0
  1702
									 TUint8* aDestBuffer,
sl@0
  1703
									 const TPoint& aPixel,
sl@0
  1704
									 TInt aLength,
sl@0
  1705
									 TUint32* aBase,
sl@0
  1706
									 TLineScanningPosition& aLineScanningPosition) const
sl@0
  1707
	{
sl@0
  1708
	TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
sl@0
  1709
	TScanLineDecompressor<E3bpp, E3bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
sl@0
  1710
	decompr(aDestBuffer, aPixel, aLineScanningPosition, iByteWidth, iByteWidth, aLength);
sl@0
  1711
	}
sl@0
  1712
sl@0
  1713
/**
sl@0
  1714
The method generates a line from compressed 24 bpp to 32 bpp bitmap data .
sl@0
  1715
@internalComponent
sl@0
  1716
@see TScanLineDecompressor
sl@0
  1717
*/
sl@0
  1718
void CBitwiseBitmap::GenerateLineFromCompressed32UBitData(
sl@0
  1719
									 TUint8* aDestBuffer,
sl@0
  1720
									 const TPoint& aPixel,
sl@0
  1721
									 TInt aLength,
sl@0
  1722
									 TUint32* aBase,
sl@0
  1723
									 TLineScanningPosition& aLineScanningPosition) const
sl@0
  1724
	{
sl@0
  1725
	TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
sl@0
  1726
	TScanLineDecompressor<E3bpp, E4bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
sl@0
  1727
sl@0
  1728
	TUint32 theByteWidthSrc = iHeader.iSizeInPixels.iWidth * 3;
sl@0
  1729
	decompr(aDestBuffer, aPixel, aLineScanningPosition, theByteWidthSrc, iByteWidth, aLength);
sl@0
  1730
	}
sl@0
  1731
sl@0
  1732
/**
sl@0
  1733
The method generates a line from compressed 32 bpp to 32 bpp bitmap data .
sl@0
  1734
@internalComponent
sl@0
  1735
@see TScanLineDecompressor
sl@0
  1736
*/
sl@0
  1737
void CBitwiseBitmap::GenerateLineFromCompressed32ABitData(
sl@0
  1738
 									 TUint8* aDestBuffer,
sl@0
  1739
 									 const TPoint& aPixel,
sl@0
  1740
 									 TInt aLength,
sl@0
  1741
 									 TUint32* aBase,
sl@0
  1742
 									 TLineScanningPosition& aLineScanningPosition) const
sl@0
  1743
	{
sl@0
  1744
	TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
sl@0
  1745
	TScanLineDecompressor<E4bpp, E4bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
sl@0
  1746
sl@0
  1747
	TUint32 theByteWidthSrc = iHeader.iSizeInPixels.iWidth * 4;
sl@0
  1748
	decompr(aDestBuffer, aPixel, aLineScanningPosition, theByteWidthSrc, iByteWidth, aLength);
sl@0
  1749
	}
sl@0
  1750
sl@0
  1751
TInt CBitwiseBitmap::DoGetScanLinePtr(TUint32*& aSlptr, TPoint& aPixel,TInt aLength,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
sl@0
  1752
	{
sl@0
  1753
	TUint8* buf=NULL;
sl@0
  1754
	HBufC8* hBuf=aLineScanningPosition.iScanLineBuffer;
sl@0
  1755
	if (!hBuf)
sl@0
  1756
		{
sl@0
  1757
		RFbsSession* session=RFbsSession::GetSession();
sl@0
  1758
		if (session)
sl@0
  1759
			{
sl@0
  1760
			hBuf=session->GetScanLineBuffer();
sl@0
  1761
			}
sl@0
  1762
		else
sl@0
  1763
			{
sl@0
  1764
			aSlptr=NULL;
sl@0
  1765
			return KErrSessionClosed;
sl@0
  1766
			}
sl@0
  1767
		aLineScanningPosition.iScanLineBuffer=hBuf;
sl@0
  1768
		}
sl@0
  1769
	__ASSERT_ALWAYS(hBuf && hBuf->Des().MaxLength() >= iByteWidth, User::Invariant());
sl@0
  1770
	buf = const_cast<TUint8*>(hBuf->Ptr());
sl@0
  1771
	switch(iHeader.iCompression)
sl@0
  1772
		{
sl@0
  1773
		case ETwelveBitRLECompression:
sl@0
  1774
			GenerateLineFromCompressedTwelveBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
sl@0
  1775
			break;
sl@0
  1776
		case EByteRLECompression:
sl@0
  1777
			GenerateLineFromCompressedEightBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
sl@0
  1778
			break;
sl@0
  1779
		case ESixteenBitRLECompression:
sl@0
  1780
			GenerateLineFromCompressedSixteenBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
sl@0
  1781
			break;
sl@0
  1782
		case ETwentyFourBitRLECompression:
sl@0
  1783
			GenerateLineFromCompressed24BitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
sl@0
  1784
			break;
sl@0
  1785
		case EThirtyTwoUBitRLECompression:
sl@0
  1786
			GenerateLineFromCompressed32UBitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
sl@0
  1787
			break;
sl@0
  1788
		case EThirtyTwoABitRLECompression:
sl@0
  1789
			GenerateLineFromCompressed32ABitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
sl@0
  1790
			break;
sl@0
  1791
		case EGenericPaletteCompression:
sl@0
  1792
			GenerateLineFromPaletteCompressedData(buf, aPixel, aLength, aBase, aLineScanningPosition);
sl@0
  1793
			break;
sl@0
  1794
		case EProprietaryCompression:
sl@0
  1795
			if (aLineScanningPosition.iRasterizer)
sl@0
  1796
				{
sl@0
  1797
				aSlptr = const_cast<TUint32*>(aLineScanningPosition.iRasterizer->ScanLine(Extra()->iSerialNumber, aPixel, aLength));
sl@0
  1798
				if (aSlptr)
sl@0
  1799
					{
sl@0
  1800
					return KErrNone;
sl@0
  1801
					}
sl@0
  1802
				}
sl@0
  1803
			WhiteFill(buf, iByteWidth, iSettings.CurrentDisplayMode());
sl@0
  1804
			break;
sl@0
  1805
		default:
sl@0
  1806
			{
sl@0
  1807
			__ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
sl@0
  1808
			return KErrNotSupported;
sl@0
  1809
			}
sl@0
  1810
		}
sl@0
  1811
	aSlptr = (TUint32*) buf;
sl@0
  1812
	return KErrNone;
sl@0
  1813
	}
sl@0
  1814
sl@0
  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
sl@0
  1816
	{
sl@0
  1817
	if (!iDataOffset)
sl@0
  1818
		return;
sl@0
  1819
sl@0
  1820
	TPoint pixel(aPixel);
sl@0
  1821
	TUint32* slptr=NULL;
sl@0
  1822
	GetScanLinePtr(slptr, aLength, pixel,aBase, aLineScanningPosition);
sl@0
  1823
	GetScanLine(slptr,aBuf,pixel,aLength,aDither,aDitherOffset,aDispMode);
sl@0
  1824
	}
sl@0
  1825
sl@0
  1826
EXPORT_C void CBitwiseBitmap::GetScanLine(TUint32*& aScanLinePtr, TDes8& aDestBuf,const TPoint& aPixel,TInt aLength,TBool aDither,
sl@0
  1827
	const TPoint& aDitherOffset,TDisplayMode aDestinationDispMode) const
sl@0
  1828
	{
sl@0
  1829
	if (!iDataOffset)
sl@0
  1830
		return;
sl@0
  1831
	TDisplayMode currentDisplayMode = iSettings.CurrentDisplayMode();
sl@0
  1832
	if (!aScanLinePtr) // if scanline pointer is null,
sl@0
  1833
		{
sl@0
  1834
		WhiteFill((TUint8*)aDestBuf.Ptr(),aDestBuf.MaxLength(),currentDisplayMode);
sl@0
  1835
		return;
sl@0
  1836
		}
sl@0
  1837
	TUint8* ptr = (TUint8*)aDestBuf.Ptr();
sl@0
  1838
	// if dest pointer is not aligned
sl@0
  1839
	if (!(TUint32(ptr)&3) && aDestinationDispMode == currentDisplayMode)
sl@0
  1840
		{
sl@0
  1841
		if (iHeader.iBitsPerPixel < 8)
sl@0
  1842
			GetScanLineExBits(aDestBuf,aPixel.iX,aLength,aScanLinePtr);
sl@0
  1843
		else
sl@0
  1844
			GetScanLineExBytes(aDestBuf,aPixel.iX,aLength,aScanLinePtr);
sl@0
  1845
		return;
sl@0
  1846
		}
sl@0
  1847
	//read the scanline in destination display format.
sl@0
  1848
	switch (aDestinationDispMode)
sl@0
  1849
		{
sl@0
  1850
	case EGray2:
sl@0
  1851
		GetScanLineGray2(aDestBuf,aPixel,aLength,aDither,aDitherOffset,aScanLinePtr);
sl@0
  1852
		break;
sl@0
  1853
	case EGray4:
sl@0
  1854
		GetScanLineGray4(aDestBuf,aPixel,aLength,aDither,aDitherOffset,aScanLinePtr);
sl@0
  1855
		break;
sl@0
  1856
	case EGray16:
sl@0
  1857
		GetScanLineGray16(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1858
		break;
sl@0
  1859
	case EGray256:
sl@0
  1860
		GetScanLineGray256(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1861
		break;
sl@0
  1862
	case EColor16:
sl@0
  1863
		GetScanLineColor16(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1864
		break;
sl@0
  1865
	case EColor256:
sl@0
  1866
		GetScanLineColor256(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1867
		break;
sl@0
  1868
	case EColor4K:
sl@0
  1869
		GetScanLineColor4K(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1870
		break;
sl@0
  1871
	case EColor64K:
sl@0
  1872
		GetScanLineColor64K(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1873
		break;
sl@0
  1874
	case EColor16M:
sl@0
  1875
		GetScanLineColor16M(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1876
		break;
sl@0
  1877
	case ERgb:
sl@0
  1878
		GetScanLineColorRgb(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1879
		break;
sl@0
  1880
	case EColor16MU:
sl@0
  1881
		GetScanLineColor16MU(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1882
		break;
sl@0
  1883
	case EColor16MA:
sl@0
  1884
		GetScanLineColor16MA(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1885
		break;
sl@0
  1886
	case EColor16MAP:
sl@0
  1887
		GetScanLineColor16MAP(aDestBuf,aPixel,aLength,aScanLinePtr);
sl@0
  1888
		break;
sl@0
  1889
	default:
sl@0
  1890
		aDestBuf.SetLength(0);
sl@0
  1891
		break;
sl@0
  1892
		};
sl@0
  1893
	}
sl@0
  1894
sl@0
  1895
EXPORT_C void CBitwiseBitmap::GetScanLine(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase) const
sl@0
  1896
	{
sl@0
  1897
	TLineScanningPosition pos(aBase);
sl@0
  1898
	TUint8* base = REINTERPRET_CAST(TUint8*,aBase);
sl@0
  1899
	const TCompressionBookMark* bookMarkPtr = NULL;
sl@0
  1900
sl@0
  1901
	GetLineScanPos(pos, bookMarkPtr, base);
sl@0
  1902
	GetScanLine(aBuf,aPixel,aLength,aDither,aDitherOffset,aDispMode,aBase,pos);
sl@0
  1903
	UpdateBookMark(pos, const_cast<TCompressionBookMark*>(bookMarkPtr), base);
sl@0
  1904
	}
sl@0
  1905
sl@0
  1906
/**
sl@0
  1907
Gets the bitmapís vertical scanline starting at the specified x co-ordinate and using
sl@0
  1908
the specified dither offset.
sl@0
  1909
Note: The method works for uncompressed bitmaps only.
sl@0
  1910
@param aBuf The buffer in which the vertical scanline will be returned.
sl@0
  1911
@param aX The x co-ordinate of the vertical scanline to get.
sl@0
  1912
@param aDitherOffset The dither offset of the bitmap.
sl@0
  1913
@param aDispMode Format to be used to write the data to the buffer.
sl@0
  1914
@param aBase The bitmap's data start address.
sl@0
  1915
*/
sl@0
  1916
EXPORT_C void CBitwiseBitmap::GetVerticalScanLine(TDes8& aBuf,TInt aX,TBool aDither,
sl@0
  1917
												  const TPoint& aDitherOffset,
sl@0
  1918
												  TDisplayMode aDispMode,
sl@0
  1919
												  TUint32* aBase,
sl@0
  1920
												  CFbsRasterizer* aRasterizer) const
sl@0
  1921
	{
sl@0
  1922
	if (iHeader.iCompression != ENoBitmapCompression && iHeader.iCompression != EProprietaryCompression)
sl@0
  1923
		{
sl@0
  1924
		__ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
sl@0
  1925
		return; //not supported for compressed bitmaps
sl@0
  1926
		}
sl@0
  1927
sl@0
  1928
	if (!iDataOffset)
sl@0
  1929
		{
sl@0
  1930
		return;
sl@0
  1931
		}
sl@0
  1932
	AdjustXCoord(aX);
sl@0
  1933
	TInt height=iHeader.iSizeInPixels.iHeight;
sl@0
  1934
	TUint32* slptr=aBase;
sl@0
  1935
	TUint8* ptr = (TUint8*)aBuf.Ptr();
sl@0
  1936
	*ptr=0;
sl@0
  1937
	const TInt wordwidth=iByteWidth>>2;
sl@0
  1938
	TInt y = 0;
sl@0
  1939
sl@0
  1940
	if (iHeader.iCompression == EProprietaryCompression)
sl@0
  1941
		{
sl@0
  1942
		if (aRasterizer)
sl@0
  1943
			{
sl@0
  1944
			slptr = const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,0), 1));
sl@0
  1945
			if (!slptr)
sl@0
  1946
				{
sl@0
  1947
				// wrong rasterizer for this extended bitmap - fill vertical scan line with white pixels
sl@0
  1948
				TInt bufLength = ByteWidth(height, aDispMode);
sl@0
  1949
				aBuf.SetLength(bufLength);
sl@0
  1950
				WhiteFill(ptr, bufLength, aDispMode);
sl@0
  1951
				return;
sl@0
  1952
				}
sl@0
  1953
			}
sl@0
  1954
		else
sl@0
  1955
			{
sl@0
  1956
			// no rasterizer - fill vertical scan line with white pixels
sl@0
  1957
			TInt bufLength = ByteWidth(height, aDispMode);
sl@0
  1958
			aBuf.SetLength(bufLength);
sl@0
  1959
			WhiteFill(ptr, bufLength, aDispMode);
sl@0
  1960
			return;
sl@0
  1961
			}
sl@0
  1962
		}
sl@0
  1963
sl@0
  1964
	switch(aDispMode)
sl@0
  1965
		{
sl@0
  1966
		case EGray2:
sl@0
  1967
			{
sl@0
  1968
			TBool oddx=(aDitherOffset.iX&1);
sl@0
  1969
			TBool oddy=(aDitherOffset.iY&1);
sl@0
  1970
			height=Min(height,(TInt)((aBuf.MaxLength())<<3));
sl@0
  1971
			aBuf.SetLength((height+7)>>3);
sl@0
  1972
			TUint8 mask=1;
sl@0
  1973
			for(TInt count=0;count<height;count++)
sl@0
  1974
				{
sl@0
  1975
				if (!mask)
sl@0
  1976
					{
sl@0
  1977
					mask=1;
sl@0
  1978
					ptr++;
sl@0
  1979
					*ptr = 0;
sl@0
  1980
					}
sl@0
  1981
				if (HashTo1bpp(GetGrayPixelEx(aX,slptr),oddx,oddy))
sl@0
  1982
					*ptr|=mask;
sl@0
  1983
				oddx^=1;
sl@0
  1984
				mask<<=1;
sl@0
  1985
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  1986
				}
sl@0
  1987
			 break;
sl@0
  1988
			}
sl@0
  1989
		case EGray4:
sl@0
  1990
			{
sl@0
  1991
			height=Min(height,(TInt)((aBuf.MaxLength())<<2));
sl@0
  1992
			aBuf.SetLength((height+3)>>2);
sl@0
  1993
			TInt shift=0;
sl@0
  1994
			TUint8 col=0;
sl@0
  1995
			if (iHeader.iBitsPerPixel==4 && aDither)
sl@0
  1996
				{
sl@0
  1997
				const TInt hasharray[4]={0,3,2,1};
sl@0
  1998
				TInt index=(aDitherOffset.iX&1)+((aDitherOffset.iY&1)<<1);
sl@0
  1999
				for(TInt count=0;count<height;count++,shift+=2)
sl@0
  2000
					{
sl@0
  2001
					if (shift==8)
sl@0
  2002
						{
sl@0
  2003
						shift=0;
sl@0
  2004
						ptr++;
sl@0
  2005
						*ptr=0;
sl@0
  2006
						}
sl@0
  2007
					col = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
sl@0
  2008
					TInt value = col / 5;
sl@0
  2009
					col%=5;
sl@0
  2010
					if (col>2) col--;
sl@0
  2011
					if (hasharray[index]<TInt(col))
sl@0
  2012
						value++;
sl@0
  2013
					value<<=shift;
sl@0
  2014
					*ptr|=value;
sl@0
  2015
					index^=1;
sl@0
  2016
					slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2017
					}
sl@0
  2018
				}
sl@0
  2019
			else
sl@0
  2020
				{
sl@0
  2021
				for(TInt count=0;count<height;count++,shift+=2)
sl@0
  2022
					{
sl@0
  2023
					if (shift==8)
sl@0
  2024
						{
sl@0
  2025
						shift=0;
sl@0
  2026
						ptr++;
sl@0
  2027
						*ptr=0;
sl@0
  2028
						}
sl@0
  2029
					col = TUint8(GetGrayPixelEx(aX,slptr) >> 6);
sl@0
  2030
					col<<=shift;
sl@0
  2031
					*ptr|=col;
sl@0
  2032
					slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2033
					}
sl@0
  2034
				}
sl@0
  2035
			 break;
sl@0
  2036
			}
sl@0
  2037
		case EGray16:
sl@0
  2038
			{
sl@0
  2039
			height = Min(height,aBuf.MaxLength()<<1);
sl@0
  2040
			aBuf.SetLength((height+1)>>1);
sl@0
  2041
			TUint8* ptrLimit = ptr + aBuf.Length() - 1;
sl@0
  2042
			while (ptr < ptrLimit)
sl@0
  2043
				{
sl@0
  2044
				*ptr = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
sl@0
  2045
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2046
				*ptr++ |= GetGrayPixelEx(aX,slptr) & 0xf0;
sl@0
  2047
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2048
				}
sl@0
  2049
			// Fill last byte.
sl@0
  2050
			// If height is odd, upper 4 bits are zeroed.
sl@0
  2051
			*ptr = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
sl@0
  2052
			if (!(height & 1))
sl@0
  2053
				{
sl@0
  2054
				// Only fill upper 4 bits of last byte if height is even. 
sl@0
  2055
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2056
				*ptr++ = GetGrayPixelEx(aX,slptr) & 0xf0;
sl@0
  2057
				}
sl@0
  2058
			break;
sl@0
  2059
			}
sl@0
  2060
		case EColor16:
sl@0
  2061
			{
sl@0
  2062
			height=Min(height,aBuf.MaxLength()<<1);
sl@0
  2063
			aBuf.SetLength((height+1)>>1);
sl@0
  2064
			TUint8* ptrLimit = ptr + aBuf.Length() - 1;
sl@0
  2065
sl@0
  2066
			while (ptr < ptrLimit)
sl@0
  2067
				{
sl@0
  2068
				*ptr = TUint8(GetRgbPixelEx(aX,slptr).Color16());
sl@0
  2069
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2070
				*ptr++ |= GetRgbPixelEx(aX,slptr).Color16() << 4;
sl@0
  2071
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2072
				}
sl@0
  2073
			// Fill last byte.
sl@0
  2074
			// If height is odd, upper 4 bits are zeroed.
sl@0
  2075
			*ptr = TUint8(GetRgbPixelEx(aX,slptr).Color16());
sl@0
  2076
			if (!(height & 1))
sl@0
  2077
				{
sl@0
  2078
				// Only fill upper 4 bits of last byte if height is even. 
sl@0
  2079
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2080
				*ptr++ = GetRgbPixelEx(aX,slptr).Color16() << 4;
sl@0
  2081
				}
sl@0
  2082
			break;
sl@0
  2083
			}
sl@0
  2084
		case EGray256:
sl@0
  2085
			{
sl@0
  2086
			height = Min(height,aBuf.MaxLength());
sl@0
  2087
			aBuf.SetLength(height);
sl@0
  2088
			TUint8* ptrLimit = ptr + height;
sl@0
  2089
			while (ptr < ptrLimit)
sl@0
  2090
				{
sl@0
  2091
				*ptr++ = GetGrayPixelEx(aX,slptr);
sl@0
  2092
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2093
				}
sl@0
  2094
			break;
sl@0
  2095
			}
sl@0
  2096
		case EColor256:
sl@0
  2097
			{
sl@0
  2098
			height = Min(height,aBuf.MaxLength());
sl@0
  2099
			aBuf.SetLength(height);
sl@0
  2100
			TUint8* ptrLimit = ptr + height;
sl@0
  2101
sl@0
  2102
			while (ptr < ptrLimit)
sl@0
  2103
				{
sl@0
  2104
				*ptr++ = TUint8(GetRgbPixelEx(aX,slptr).Color256());
sl@0
  2105
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2106
				}
sl@0
  2107
			break;
sl@0
  2108
			}
sl@0
  2109
		case EColor4K:
sl@0
  2110
			{
sl@0
  2111
			height = Min(height,aBuf.MaxLength() >> 1);
sl@0
  2112
			aBuf.SetLength(height << 1);
sl@0
  2113
			TUint16* dwordPtr = (TUint16*)ptr;
sl@0
  2114
			TUint16* ptrLimit = dwordPtr + height;
sl@0
  2115
sl@0
  2116
			while (dwordPtr < ptrLimit)
sl@0
  2117
				{
sl@0
  2118
				*dwordPtr++ = TUint16(GetRgbPixelEx(aX,slptr)._Color4K());
sl@0
  2119
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2120
				}
sl@0
  2121
			break;
sl@0
  2122
			}
sl@0
  2123
		case EColor64K:
sl@0
  2124
			{
sl@0
  2125
			height = Min(height,aBuf.MaxLength() >> 1);
sl@0
  2126
			aBuf.SetLength(height << 1);
sl@0
  2127
			TUint16* dwordPtr = (TUint16*)ptr;
sl@0
  2128
			TUint16* ptrLimit = dwordPtr + height;
sl@0
  2129
sl@0
  2130
			while (dwordPtr < ptrLimit)
sl@0
  2131
				{
sl@0
  2132
				*dwordPtr++ = TUint16(GetRgbPixelEx(aX,slptr)._Color64K());
sl@0
  2133
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2134
				}
sl@0
  2135
			break;
sl@0
  2136
			}
sl@0
  2137
		case EColor16M:
sl@0
  2138
			{
sl@0
  2139
			height = Min(height,aBuf.MaxLength() / 3);
sl@0
  2140
			aBuf.SetLength(height * 3);
sl@0
  2141
			const TUint8* ptrLimit = ptr + (height * 3);
sl@0
  2142
sl@0
  2143
			while (ptr < ptrLimit)
sl@0
  2144
				{
sl@0
  2145
				const TInt color16M = GetRgbPixelEx(aX,slptr)._Color16M();
sl@0
  2146
				*ptr++ = TUint8(color16M);
sl@0
  2147
				*ptr++ = TUint8(color16M >> 8);
sl@0
  2148
				*ptr++ = TUint8(color16M >> 16);
sl@0
  2149
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2150
				}
sl@0
  2151
			break;
sl@0
  2152
			}
sl@0
  2153
		case ERgb:
sl@0
  2154
		case EColor16MU:
sl@0
  2155
		case EColor16MA:
sl@0
  2156
		case EColor16MAP:
sl@0
  2157
			{
sl@0
  2158
			height = Min(height,aBuf.MaxLength() >> 2);
sl@0
  2159
			aBuf.SetLength(height << 2);
sl@0
  2160
			TUint32* pixelPtr = (TUint32*)ptr;
sl@0
  2161
			TUint32* pixelPtrLimit = pixelPtr + height;
sl@0
  2162
sl@0
  2163
			if (aDispMode == EColor16MAP && iSettings.CurrentDisplayMode() == EColor16MA)
sl@0
  2164
				while (pixelPtr < pixelPtrLimit)
sl@0
  2165
				{
sl@0
  2166
				*pixelPtr++ = NonPMA2PMAPixel(*(slptr + aX));
sl@0
  2167
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2168
				}
sl@0
  2169
			else if (aDispMode == EColor16MAP && iSettings.CurrentDisplayMode() == EColor16MAP)
sl@0
  2170
				while (pixelPtr < pixelPtrLimit)
sl@0
  2171
				{
sl@0
  2172
				*pixelPtr++ = *(slptr + aX);
sl@0
  2173
				slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2174
				}
sl@0
  2175
			else if (aDispMode == EColor16MU)
sl@0
  2176
				while (pixelPtr < pixelPtrLimit)
sl@0
  2177
					{
sl@0
  2178
					*pixelPtr++ = GetRgbPixelEx(aX, slptr).Internal() | 0xFF000000;
sl@0
  2179
					slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2180
					}
sl@0
  2181
			else
sl@0
  2182
				while (pixelPtr < pixelPtrLimit)
sl@0
  2183
					{
sl@0
  2184
					*pixelPtr++ = GetRgbPixelEx(aX, slptr).Internal();
sl@0
  2185
					slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
sl@0
  2186
					}
sl@0
  2187
			break;
sl@0
  2188
			}
sl@0
  2189
		default:
sl@0
  2190
			aBuf.SetLength(0);
sl@0
  2191
		}
sl@0
  2192
	}
sl@0
  2193
sl@0
  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
sl@0
  2195
	{
sl@0
  2196
	TLineScanningPosition pos(aBase);
sl@0
  2197
	StretchScanLine(aBuf,aPixel,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,pos);
sl@0
  2198
	}
sl@0
  2199
sl@0
  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
sl@0
  2201
	{
sl@0
  2202
	if (!iDataOffset)
sl@0
  2203
		return;
sl@0
  2204
	TInt x=aPixel.iX,y=aPixel.iY;
sl@0
  2205
	if (x>=iHeader.iSizeInPixels.iWidth || x<-iHeader.iSizeInPixels.iWidth)
sl@0
  2206
		x%=iHeader.iSizeInPixels.iWidth;
sl@0
  2207
	if (y>=iHeader.iSizeInPixels.iHeight || y<-iHeader.iSizeInPixels.iHeight)
sl@0
  2208
		y%=iHeader.iSizeInPixels.iHeight;
sl@0
  2209
	if (x<0) x+=iHeader.iSizeInPixels.iWidth;
sl@0
  2210
	if (y<0) y+=iHeader.iSizeInPixels.iHeight;
sl@0
  2211
	if (aStretchLength<aOrgLen)
sl@0
  2212
		DoCompressScanLine(aBuf,x,y,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,aLineScanningPosition);
sl@0
  2213
	else
sl@0
  2214
		DoStretchScanLine(aBuf,x,y,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,aLineScanningPosition);
sl@0
  2215
	}
sl@0
  2216
sl@0
  2217
EXPORT_C TUint32* CBitwiseBitmap::ScanLineAddress(TUint32* aBase,TUint aY) const
sl@0
  2218
	{
sl@0
  2219
	if (aY == 0 || iDataOffset == 0)
sl@0
  2220
		return aBase;
sl@0
  2221
sl@0
  2222
	if (aY >= TUint(iHeader.iSizeInPixels.iHeight))
sl@0
  2223
		aY %= iHeader.iSizeInPixels.iHeight;
sl@0
  2224
sl@0
  2225
	return aBase + (aY * (DataStride() >> 2));
sl@0
  2226
	}
sl@0
  2227
sl@0
  2228
TUint32* CBitwiseBitmap::DataAddress() const
sl@0
  2229
	{
sl@0
  2230
	if (iDataOffset==0) return(NULL);
sl@0
  2231
sl@0
  2232
	if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid)   // RHardwareBitmap
sl@0
  2233
		{
sl@0
  2234
		RHardwareBitmap hwb(iDataOffset);	// iDataOffset = handle for hardware bitmap
sl@0
  2235
		TAcceleratedBitmapInfo info;
sl@0
  2236
		const TInt ret = hwb.GetInfo(info);
sl@0
  2237
		return ret!=KErrNone ? NULL : (reinterpret_cast<TUint32*>(info.iAddress));
sl@0
  2238
		}
sl@0
  2239
sl@0
  2240
	if (iHeap == NULL)
sl@0
  2241
		return(reinterpret_cast<TUint32*>((TUint8*)this+iDataOffset));
sl@0
  2242
	return(reinterpret_cast<TUint32*>(iPile->ChunkBase()+iDataOffset));
sl@0
  2243
	}
sl@0
  2244
sl@0
  2245
EXPORT_C TInt CBitwiseBitmap::DataStride() const
sl@0
  2246
	{
sl@0
  2247
	return iByteWidth;
sl@0
  2248
	}
sl@0
  2249
sl@0
  2250
TUint32 CBitwiseBitmap::HashTo2bpp(TUint32 aGray256,TInt aDitherIndex) const
sl@0
  2251
	{
sl@0
  2252
	static const TUint hasharray[4]={0,3,2,1};
sl@0
  2253
	TInt gray16 = aGray256 >> 4;
sl@0
  2254
	TInt gray4 = gray16 + 1;
sl@0
  2255
	gray4 += gray4 << 1;
sl@0
  2256
	gray4 >>= 4;
sl@0
  2257
	gray16 %= 5;
sl@0
  2258
	if (gray16 > 2)
sl@0
  2259
		gray16--;
sl@0
  2260
	if (hasharray[aDitherIndex] < TUint(gray16))
sl@0
  2261
		gray4++;
sl@0
  2262
	return gray4;
sl@0
  2263
	}
sl@0
  2264
sl@0
  2265
TUint32 CBitwiseBitmap::HashTo1bpp(TUint32 aGray256,TBool aOddX,TBool aOddY) const
sl@0
  2266
	{
sl@0
  2267
	TUint32 aGray4 = aGray256 >> 6;
sl@0
  2268
	switch(aGray4)
sl@0
  2269
		{
sl@0
  2270
		case 3:
sl@0
  2271
			return 1;
sl@0
  2272
		case 2:
sl@0
  2273
			{
sl@0
  2274
			if (aOddX && aOddY)
sl@0
  2275
				return 0;
sl@0
  2276
			else
sl@0
  2277
				return 1;
sl@0
  2278
			}
sl@0
  2279
		case 1:
sl@0
  2280
			{
sl@0
  2281
			if ((aOddX && aOddY) || (!aOddX && !aOddY))
sl@0
  2282
				return 1;
sl@0
  2283
			}
sl@0
  2284
			//coverity [fallthrough]
sl@0
  2285
		default:
sl@0
  2286
			return 0;
sl@0
  2287
		}
sl@0
  2288
	}
sl@0
  2289
sl@0
  2290
/**
sl@0
  2291
Tests whether or not the bitmap is monochrome.
sl@0
  2292
Monochrome bitmaps have a display-mode of 1 bit-per-pixel.
sl@0
  2293
Note: The method works for uncompressed bitmaps only.
sl@0
  2294
@param aBase Bitmap's data base address
sl@0
  2295
@return True if the bitmap is monochrome; false otherwise.
sl@0
  2296
*/
sl@0
  2297
EXPORT_C TBool CBitwiseBitmap::IsMonochrome(TUint32* aBase) const
sl@0
  2298
	{
sl@0
  2299
	if (IsCompressed())
sl@0
  2300
		{
sl@0
  2301
		__ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
sl@0
  2302
		return EFalse;  // Not currently supported for compressed bitmaps
sl@0
  2303
		}
sl@0
  2304
sl@0
  2305
	if (!iDataOffset)
sl@0
  2306
		{
sl@0
  2307
		return(EFalse);
sl@0
  2308
		}
sl@0
  2309
	TInt bitwidth=iHeader.iBitsPerPixel*iHeader.iSizeInPixels.iWidth;
sl@0
  2310
	if(iHeader.iBitsPerPixel == 12)
sl@0
  2311
		{//EColor4K mode - 1 pixel occupies 16 bits, most significant 4 bits are not used.
sl@0
  2312
		bitwidth=16*iHeader.iSizeInPixels.iWidth;
sl@0
  2313
		}
sl@0
  2314
	TInt wordwidth=bitwidth>>5;
sl@0
  2315
	TInt endshift=32-(bitwidth&0x1f);
sl@0
  2316
	TInt endmask=0;
sl@0
  2317
	if (endshift<32) endmask=0xffffffff>>endshift;
sl@0
  2318
	TUint32* bitptr=aBase;
sl@0
  2319
	//In a loop from first to last scanline:
sl@0
  2320
	//Check each pixel - is it monochrome or not (pixel color must be BLACK or WHITE).
sl@0
  2321
	//Get next scanline.
sl@0
  2322
	TUint32* endbitptr=bitptr+wordwidth;
sl@0
  2323
	for(TInt row=0;row<iHeader.iSizeInPixels.iHeight;row++)
sl@0
  2324
		{
sl@0
  2325
		if(iHeader.iBitsPerPixel == 24)
sl@0
  2326
			{//1 word contains 1 pixel and 8 bits from the next pixel.
sl@0
  2327
			for(TInt x=0;x<iHeader.iSizeInPixels.iWidth;x++)
sl@0
  2328
				{
sl@0
  2329
				TUint8* scanLine = reinterpret_cast <TUint8*> (bitptr) + x * 3;
sl@0
  2330
				TUint color16M = *scanLine++;
sl@0
  2331
				color16M |= (*scanLine++) << 8;
sl@0
  2332
				color16M |= (*scanLine++) << 16;
sl@0
  2333
				if (IsWordMonochrome(color16M)==EFalse)
sl@0
  2334
					return(EFalse);
sl@0
  2335
				}
sl@0
  2336
			}
sl@0
  2337
		else
sl@0
  2338
			{
sl@0
  2339
			TUint32* tmpbitptr=bitptr;
sl@0
  2340
			while(tmpbitptr<endbitptr)
sl@0
  2341
				if (IsWordMonochrome(*tmpbitptr++)==EFalse)
sl@0
  2342
					return(EFalse);
sl@0
  2343
			if (endmask)
sl@0
  2344
				if (IsWordMonochrome(*endbitptr&endmask)==EFalse)
sl@0
  2345
					return(EFalse);
sl@0
  2346
			}
sl@0
  2347
		bitptr+=wordwidth;
sl@0
  2348
		endbitptr+=wordwidth;
sl@0
  2349
		}
sl@0
  2350
	return(ETrue);
sl@0
  2351
	}
sl@0
  2352
sl@0
  2353
TBool CBitwiseBitmap::IsWordMonochrome(TUint32 aWord) const
sl@0
  2354
	{
sl@0
  2355
	TDisplayMode displayMode = iSettings.CurrentDisplayMode();
sl@0
  2356
	switch(displayMode)
sl@0
  2357
		{
sl@0
  2358
		case EGray2:
sl@0
  2359
			return ETrue;
sl@0
  2360
		case EGray4:
sl@0
  2361
			{
sl@0
  2362
			TUint32 lowerbits=aWord&0x55555555;
sl@0
  2363
			TUint32 upperbits=(aWord>>1)&0x55555555;
sl@0
  2364
			if (lowerbits^upperbits)
sl@0
  2365
				return EFalse;
sl@0
  2366
			return ETrue;
sl@0
  2367
			}
sl@0
  2368
		case EGray16:
sl@0
  2369
		case EColor16:
sl@0
  2370
			{
sl@0
  2371
			if (aWord==0xffffffff || aWord==0)
sl@0
  2372
				return ETrue;
sl@0
  2373
			for(TInt count=0;count<8;count++)
sl@0
  2374
				{
sl@0
  2375
				TUint32 nibble=aWord&0xf;
sl@0
  2376
				if ((nibble>0) && (nibble<0xf))
sl@0
  2377
					return EFalse;
sl@0
  2378
				aWord>>=4;
sl@0
  2379
				}
sl@0
  2380
			return ETrue;
sl@0
  2381
			}
sl@0
  2382
		case EGray256:
sl@0
  2383
		case EColor256:
sl@0
  2384
			{
sl@0
  2385
			TUint8* bytePtr = (TUint8*)&aWord;
sl@0
  2386
			TUint8* bytePtrLimit = bytePtr + 4;
sl@0
  2387
			while (bytePtr < bytePtrLimit)
sl@0
  2388
				{
sl@0
  2389
				if (*bytePtr && (*bytePtr != 0xff))
sl@0
  2390
					return EFalse;
sl@0
  2391
				bytePtr++;
sl@0
  2392
				}
sl@0
  2393
			return ETrue;
sl@0
  2394
			}
sl@0
  2395
		case EColor4K:
sl@0
  2396
			{
sl@0
  2397
			aWord &= 0x0fff0fff;
sl@0
  2398
			TUint16 color4K = (TUint16)aWord;
sl@0
  2399
			if (color4K && (color4K != 0xfff))
sl@0
  2400
				return EFalse;
sl@0
  2401
			color4K = (TUint16)(aWord >> 16);
sl@0
  2402
			if (color4K && (color4K != 0xfff))
sl@0
  2403
				return EFalse;
sl@0
  2404
			return ETrue;
sl@0
  2405
			}
sl@0
  2406
		case EColor64K:
sl@0
  2407
			{
sl@0
  2408
			TUint16 color64K = (TUint16)aWord;
sl@0
  2409
			if (color64K && (color64K != 0xffff))
sl@0
  2410
				return EFalse;
sl@0
  2411
			color64K = (TUint16)(aWord >> 16);
sl@0
  2412
			if (color64K && (color64K != 0xffff))
sl@0
  2413
				return EFalse;
sl@0
  2414
			return ETrue;
sl@0
  2415
			}
sl@0
  2416
		case EColor16M:
sl@0
  2417
		case EColor16MU:
sl@0
  2418
		case EColor16MA:
sl@0
  2419
		case EColor16MAP:
sl@0
  2420
			{
sl@0
  2421
			aWord &= 0xffffff;
sl@0
  2422
			if (aWord && (aWord != 0x00ffffff))
sl@0
  2423
				return EFalse;
sl@0
  2424
			return ETrue;
sl@0
  2425
			}
sl@0
  2426
		default:
sl@0
  2427
			return EFalse;
sl@0
  2428
		}
sl@0
  2429
	}
sl@0
  2430
sl@0
  2431
EXPORT_C TBool CBitwiseBitmap::IsLargeBitmap() const
sl@0
  2432
	{
sl@0
  2433
	if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid)
sl@0
  2434
		return EFalse; // RHardwareBitmap
sl@0
  2435
sl@0
  2436
	if (iHeap==NULL) return(EFalse); // rom bitmap
sl@0
  2437
sl@0
  2438
	// Consider all RAM bitmaps large, so that legacy applications always
sl@0
  2439
	// call LockHeap()/UnlockHeap() around DataAddress(), which allows
sl@0
  2440
	// better handling of hardware acceleration caches, if present.
sl@0
  2441
	// Note that, since the large bitmap threshold has always been in the
sl@0
  2442
	// documentation, it is not guaranteed that legacy applications call
sl@0
  2443
	// this function to determine whether a bitmap is large or not.
sl@0
  2444
	return ETrue;
sl@0
  2445
	}
sl@0
  2446
sl@0
  2447
EXPORT_C TInt CBitwiseBitmap::HardwareBitmapHandle() const
sl@0
  2448
	{
sl@0
  2449
	if(iUid.iUid!=KCBitwiseBitmapHardwareUid.iUid)
sl@0
  2450
		return 0;
sl@0
  2451
	return iDataOffset; // Really the handle
sl@0
  2452
	}
sl@0
  2453
sl@0
  2454
/**
sl@0
  2455
Set a flag to indicate that this bitmap has to be compressed in the FBServer background thread
sl@0
  2456
@return KErrNone if possible to compress, KErrAlreadyExists if already compressed
sl@0
  2457
*/
sl@0
  2458
EXPORT_C TInt CBitwiseBitmap::CheckBackgroundCompressData()
sl@0
  2459
	{
sl@0
  2460
	switch (iHeader.iBitsPerPixel)
sl@0
  2461
		{
sl@0
  2462
	case 1:
sl@0
  2463
	case 2:
sl@0
  2464
	case 4:
sl@0
  2465
	case 8:
sl@0
  2466
	case 12:
sl@0
  2467
	case 16:
sl@0
  2468
	case 24:
sl@0
  2469
	case 32:
sl@0
  2470
		break;
sl@0
  2471
	default:
sl@0
  2472
		return KErrNotSupported;
sl@0
  2473
		}
sl@0
  2474
	// Return if the bitmap is already compressed.
sl@0
  2475
	if (iHeader.iCompression != ENoBitmapCompression)
sl@0
  2476
		return KErrAlreadyExists;
sl@0
  2477
sl@0
  2478
	// See if it's possible to allocate memory.
sl@0
  2479
	if (iHeap == NULL || iPile == NULL)
sl@0
  2480
		return KErrNoMemory;
sl@0
  2481
sl@0
  2482
	return KErrNone;
sl@0
  2483
	}
sl@0
  2484
sl@0
  2485
sl@0
  2486
sl@0
  2487
/**
sl@0
  2488
Compress a bitmap if possible.
sl@0
  2489
If the bitmap is already compressed, or if compression yields no decrease in size, do nothing,
sl@0
  2490
but return success (KErrNone).
sl@0
  2491
@return KErrNone if successful, otherwise a system wide error code.
sl@0
  2492
*/
sl@0
  2493
EXPORT_C TInt CBitwiseBitmap::CompressData()
sl@0
  2494
	{
sl@0
  2495
	switch (iHeader.iBitsPerPixel)
sl@0
  2496
		{
sl@0
  2497
	case 1:
sl@0
  2498
	case 2:
sl@0
  2499
	case 4:
sl@0
  2500
	case 8:
sl@0
  2501
	case 12:
sl@0
  2502
	case 16:
sl@0
  2503
	case 24:
sl@0
  2504
	case 32:
sl@0
  2505
		break;
sl@0
  2506
	default:
sl@0
  2507
		return KErrNone;
sl@0
  2508
		}
sl@0
  2509
	// Return if the bitmap is already compressed.
sl@0
  2510
	if (iHeader.iCompression != ENoBitmapCompression)
sl@0
  2511
		return KErrNone;
sl@0
  2512
sl@0
  2513
	// Find out if compression is possible and return if not.
sl@0
  2514
	TUint8* data = (TUint8*)DataAddress();
sl@0
  2515
	TInt data_bytes = iHeader.iBitmapSize - iHeader.iStructSize;
sl@0
  2516
sl@0
  2517
	//Update the padding bitmap data to speedup the RLE Compression
sl@0
  2518
	UpdatePaddingData((TUint32*)data);
sl@0
  2519
sl@0
  2520
	TInt compressed_data_bytes = (SizeOfDataCompressed((TUint8*)data,data_bytes) + 3) / 4 * 4;
sl@0
  2521
sl@0
  2522
	if (!data || !data_bytes)
sl@0
  2523
		return KErrNone;
sl@0
  2524
sl@0
  2525
	//  	 if (compressed_data_bytes >= data_bytes)
sl@0
  2526
	//  It now attempts to check whether compression is worth while.  (speed vs space saving)
sl@0
  2527
	__ASSERT_DEBUG(KCompressionThreshold >=0 && KCompressionThreshold <= 256, ::Panic(EFbsInvalidCompressionThreshold));
sl@0
  2528
	if (compressed_data_bytes >= (data_bytes * KCompressionThreshold) >> 8)
sl@0
  2529
		return KErrNone;
sl@0
  2530
sl@0
  2531
	// See if it's possible to allocate memory.
sl@0
  2532
	if (iHeap == NULL || iPile == NULL)
sl@0
  2533
		return KErrNoMemory;
sl@0
  2534
sl@0
  2535
	// Create a buffer to receive the compressed data.
sl@0
  2536
	TUint8* compressed_data = NULL;
sl@0
  2537
	TInt allocSize = compressed_data_bytes;
sl@0
  2538
	TBool bookMark = EFalse;
sl@0
  2539
	if (allocSize > KCompressionBookMarkThreshold)
sl@0
  2540
		{
sl@0
  2541
		allocSize += sizeof(TCompressionBookMark) + 4;
sl@0
  2542
		bookMark = ETrue;
sl@0
  2543
		}
sl@0
  2544
	compressed_data = iPile->Alloc(allocSize);
sl@0
  2545
	if (!compressed_data)
sl@0
  2546
		return KErrNoMemory;
sl@0
  2547
	if (bookMark)
sl@0
  2548
		{
sl@0
  2549
		TCompressionBookMark emptyBookmark;
sl@0
  2550
		*((TCompressionBookMark*)(compressed_data + compressed_data_bytes + 4)) = emptyBookmark;
sl@0
  2551
		}
sl@0
  2552
	iDataOffset = compressed_data - iPile->ChunkBase();
sl@0
  2553
	iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + compressed_data_bytes;
sl@0
  2554
	iHeader.iCompression = CompressionType(iHeader.iBitsPerPixel, iHeader.iColor);
sl@0
  2555
sl@0
  2556
	// Compress the data into a stream over the new buffer.
sl@0
  2557
	TPtr8 output_ptr(compressed_data,compressed_data_bytes);
sl@0
  2558
	RDesWriteStream output_stream(output_ptr);
sl@0
  2559
	// This function cannot leave - but trap it anyway till I am fully satisfied about that.
sl@0
  2560
	TRAP_IGNORE(DoExternalizeDataCompressedL(output_stream,data,data_bytes));
sl@0
  2561
	output_stream.Close();
sl@0
  2562
sl@0
  2563
	iIsCompressedInRAM = ETrue;
sl@0
  2564
	// Free the old data.
sl@0
  2565
	iPile->Free(data);
sl@0
  2566
sl@0
  2567
	return KErrNone;
sl@0
  2568
	}
sl@0
  2569
sl@0
  2570
/**
sl@0
  2571
Compress a bitmap if possible.
sl@0
  2572
If the bitmap is already compressed, or if compression yields no decrease in size, do nothing,
sl@0
  2573
but return success (KErrNone).
sl@0
  2574
@publishedAll
sl@0
  2575
@param aScheme The type of bitmap file compression.
sl@0
  2576
@return KErrNone if successful, otherwise a system wide error code.
sl@0
  2577
*/
sl@0
  2578
EXPORT_C TInt CBitwiseBitmap::CompressData(TBitmapfileCompressionScheme aScheme)
sl@0
  2579
	{
sl@0