First public contribution.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
19 #include <graphicsaccelerator.h>
20 #include <graphics/lookuptable.h>
21 #include <graphics/blendingalgorithms.h>
22 #include <graphics/bitmapuid.h>
25 #include "ShiftedFileStore.h"
26 #include "CompileAssert.h"
27 #include "CompressionBookmark.h"
28 #include "BitmapCompr.h"
30 #include "fbsrasterizer.h"
32 #include "BitwiseBitmap.inl"
33 #include "bitmapconst.h"
41 const TInt KMaxPixelSize = KMaxTInt / 4; // Maximum pixel size to avoid some overflow problems
42 const TUint KMaxByteSize = TUint(KMaxTInt / 2); // Maximum byte size to avoid other overflow problems
47 GLREF_C void Panic(TFbsPanic aPanic);
49 #define COLOR_VALUE(ScanLinePtr, XPos) (*((ScanLinePtr) + ((XPos) >> 5)) & ( 1 << ((XPos) & 0x1F)))
51 EXPORT_C void CBitwiseBitmap::operator delete(TAny *aThis)
53 if (((CBitwiseBitmap*)aThis)->iHeap)
54 ((CBitwiseBitmap*)aThis)->iHeap->Free(aThis);
57 EXPORT_C CBitwiseBitmap::CBitwiseBitmap(RHeap* aHeap,CChunkPile* aPile):
58 iUid(KCBitwiseBitmapUid),
64 iIsCompressedInRAM(EFalse)
66 //CBitwiseBitmap size can't be changed! If the bitmap is ROM based,
67 //then CBitwiseBitmap object is not created, but CBitwiseBitmap pointer is
68 //used to access ROM based bitmap data.
69 //The following line is a part of CFbsBitmap::DoLoad(...) source code:
70 //iRomPointer=(CBitwiseBitmap*)(((TUint8*)rompointer)+offset);
71 //We have to preserve data compatibility with already existing ROM bitmaps.
74 KCBitwiseBitmapSize = 72
76 COMPILE_TIME_ASSERT(sizeof(CBitwiseBitmap) == KCBitwiseBitmapSize);
77 #ifdef SYMBIAN_DEBUG_FBS_LOCKHEAP
78 Extra()->iLockCount = 0;
79 Extra()->iThreadId = TThreadId(KNullThreadId);
81 Extra()->iTouchCount = 0;
82 Extra()->iSerialNumber = 0;
85 EXPORT_C CBitwiseBitmap::~CBitwiseBitmap()
90 EXPORT_C void CBitwiseBitmap::Reset()
94 if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid)
96 RHardwareBitmap hwb(iDataOffset); // iDataOffset = handle for hardware bitmap
100 if (iPile) iPile->Free(DataAddress());
102 iUid.iUid = KCBitwiseBitmapUid.iUid;
104 iSettings.SetDisplayModes(ENone);
106 iHeader=SEpocBitmapHeader();
107 iIsCompressedInRAM=EFalse;
110 EXPORT_C TUid CBitwiseBitmap::Uid() const
115 EXPORT_C TInt CBitwiseBitmap::Construct(const TSize& aSize,TDisplayMode aDispMode,TUid aCreatorUid)
117 if (iHeap == NULL || iPile == NULL)
120 if (aSize.iWidth > KMaxPixelSize || aSize.iHeight > KMaxPixelSize)
126 iSettings.SetDisplayModes(aDispMode);
127 iByteWidth = ByteWidth(aSize.iWidth,aDispMode);
129 TInt64 hugeDataSize = TInt64(aSize.iHeight) * TInt64(iByteWidth);
130 if (I64HIGH(hugeDataSize) != 0 || I64LOW(hugeDataSize) > KMaxByteSize)
133 TInt dataSize = I64LOW(hugeDataSize);
134 iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + dataSize;
135 iHeader.iStructSize = sizeof(SEpocBitmapHeader);
136 iHeader.iSizeInPixels = aSize;
137 iHeader.iSizeInTwips = TSize(0,0);
138 iHeader.iBitsPerPixel = Bpp(aDispMode);
139 iHeader.iColor = IsColor(aDispMode);
140 iHeader.iPaletteEntries = 0;
141 iHeader.iCompression = ENoBitmapCompression;
143 if (aSize.iHeight && aSize.iWidth)
145 if(aCreatorUid!=KUidCFbsBitmapCreation)
148 TAcceleratedBitmapInfo info;
149 TInt ret = hwb.Create(aDispMode,aSize,aCreatorUid);
151 ret = hwb.GetInfo(info);
158 iSettings.SetVolatileBitmap();
159 data = info.iAddress;
160 dataSize = info.iLinePitch*info.iSize.iHeight;
161 __ASSERT_DEBUG(info.iLinePitch >= iByteWidth, ::Panic(EFbsHardwareBitmapError));
162 iByteWidth = info.iLinePitch;
164 iDataOffset = hwb.iHandle; // iDataOffset = handle for hardware bitmap
165 iUid.iUid = KCBitwiseBitmapHardwareUid.iUid;
166 #ifdef SYMBIAN_DISABLE_HARDWARE_BITMAP_WHITEFILL
172 data = iPile->Alloc(dataSize);
173 iDataOffset = data - iPile->ChunkBase();
179 return(KErrNoMemory); // no memory exit point
183 if (dataSize < KMaxLargeBitmapAlloc || aDispMode == EColor4K || iUid.iUid == KCBitwiseBitmapHardwareUid.iUid)
185 WhiteFill(data,dataSize,aDispMode);
188 return KErrNone; // success exit point
192 EXPORT_C TInt CBitwiseBitmap::ConstructExtended(const TSize& aSize, TDisplayMode aDispMode, TUid aType, TInt aDataSize)
194 if (iHeap == NULL || iPile == NULL)
196 if (aSize.iWidth > KMaxPixelSize || aSize.iHeight > KMaxPixelSize)
198 if (aType.iUid == KCBitwiseBitmapUid.iUid || aType.iUid == KCBitwiseBitmapHardwareUid.iUid)
199 return KErrArgument; // make sure the extended bitmap type is not one of the standard types
200 if (aDataSize > KMaxByteSize)
204 iSettings.SetDisplayModes(aDispMode);
205 iByteWidth = ByteWidth(aSize.iWidth, aDispMode);
206 iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + aDataSize;
207 iHeader.iStructSize = sizeof(SEpocBitmapHeader);
208 iHeader.iSizeInPixels = aSize;
209 iHeader.iSizeInTwips = TSize(0,0);
210 iHeader.iBitsPerPixel = Bpp(aDispMode);
211 iHeader.iColor = IsColor(aDispMode);
212 iHeader.iPaletteEntries = 0;
213 iHeader.iCompression = EProprietaryCompression;
214 TUint8* data = iPile->Alloc(aDataSize);
220 iDataOffset = data - iPile->ChunkBase();
225 EXPORT_C void CBitwiseBitmap::ConstructL(RFs& aFs,const TDesC& aFilename,TInt32 aId,TUint aFileOffset)
227 //If aFileOffset != 0 then aFilename is a file with an embedded MBM file section at the end.
228 //The implementation uses the fact that mbm files are implemented as
229 //filestores and stream ID is actually the offset from the beginning of the filestore.
230 //If stream ID changes its meaning in the future -
231 //the method implementation has to be reviewed and changed too.
232 User::LeaveIfNull(iHeap);
233 User::LeaveIfNull(iPile);
234 TUint fileMode = EFileRead;
235 if(aFileOffset != 0) //This is a file with an embedded MBM file section at the end.
236 fileMode |= EFileShareReadersOnly;
237 CShiftedFileStore* filestore = CShiftedFileStore::OpenLC(aFs,aFilename,fileMode,aFileOffset);
238 TStreamId streamid = filestore->Root();
239 //TStreamId is the offset from the beggining of the file.
240 //Obviously, if the bitmap file section is at the middle of the physical file,
241 //we should add aFileOffset value to TStreamId value and use it.
242 TStreamId streamid2(streamid.Value() + aFileOffset);
243 RStoreReadStream readstream;
244 readstream.OpenLC(*filestore,streamid2);
245 TInt numbitmaps = readstream.ReadInt32L();
246 if (aId < 0 || aId >= numbitmaps)
247 User::Leave(KErrEof);
249 TStreamId bmpstreamid;
250 bmpstreamid.InternalizeL(readstream);
251 TStreamId bmpstreamid2(bmpstreamid.Value() + aFileOffset);
252 for (TInt count = 0; count < aId; count++)
254 bmpstreamid2.InternalizeL(readstream);
255 bmpstreamid2 = TStreamId(bmpstreamid2.Value() + aFileOffset);
258 CleanupStack::PopAndDestroy();
259 RStoreReadStream bmpstream;
260 bmpstream.OpenLC(*filestore,bmpstreamid2);
261 InternalizeL(bmpstream);
262 CleanupStack::PopAndDestroy(2);
265 EXPORT_C void CBitwiseBitmap::ConstructL(RFile& aFile,TInt32 aId,TUint aFileOffset)
267 //If aFileOffset != 0 then aFilename is a file with an embedded MBM file section at the end.
268 //The implementation uses the fact that mbm files are implemented as
269 //filestores and stream ID is actually the offset from the beginning of the filestore.
270 //If stream ID changes its meaning in the future -
271 //the method implementation has to be reviewed and changed too.
272 User::LeaveIfNull(iHeap);
273 User::LeaveIfNull(iPile);
275 CShiftedFileStore* filestore = CShiftedFileStore::FromL(aFile,aFileOffset);
276 CleanupStack::PushL(filestore);
277 TStreamId streamid = filestore->Root();
278 //TStreamId is the offset from the beggining of the file.
279 //Obviously, if the bitmap file section is at the middle of the physical file,
280 //we should add aFileOffset value to TStreamId value and use it.
281 TStreamId streamid2(streamid.Value() + aFileOffset);
282 RStoreReadStream readstream;
283 readstream.OpenLC(*filestore,streamid2);
284 TInt numbitmaps = readstream.ReadInt32L();
285 if (aId < 0 || aId >= numbitmaps)
286 User::Leave(KErrEof);
287 //Retrieving the streamid of the bitmap of that id from the file
288 TStreamId bmpstreamid;
289 bmpstreamid.InternalizeL(readstream);
290 TStreamId bmpstreamid2(bmpstreamid.Value() + aFileOffset);
291 for (TInt count = 0; count < aId; count++)
293 bmpstreamid2.InternalizeL(readstream);
294 bmpstreamid2 = TStreamId(bmpstreamid2.Value() + aFileOffset);
296 //Use the streamid found to initialize the bitmap raw data in the memory
297 CleanupStack::PopAndDestroy(&readstream);
298 RStoreReadStream bmpstream;
299 bmpstream.OpenLC(*filestore,bmpstreamid2);
300 InternalizeL(bmpstream);
301 CleanupStack::PopAndDestroy(2,filestore);
305 EXPORT_C void CBitwiseBitmap::ConstructL(CShiftedFileStore* aFileStore,TStreamId aStreamId)
307 User::LeaveIfNull(iHeap);
308 User::LeaveIfNull(iPile);
310 RStoreReadStream bmpstream;
311 bmpstream.OpenLC(*aFileStore,aStreamId);
312 InternalizeL(bmpstream);
313 CleanupStack::PopAndDestroy();
316 EXPORT_C TInt CBitwiseBitmap::CopyData(const CBitwiseBitmap& aSourceBitmap)
318 __ASSERT_DEBUG(iHeap && iPile, ::Panic(EFbsPanicBitmapDataCopy));
319 __ASSERT_DEBUG(!iIsCompressedInRAM, ::Panic(EFbsPanicBitmapDataCopy));
320 __ASSERT_DEBUG(iUid.iUid == KCBitwiseBitmapUid.iUid, ::Panic(EFbsPanicBitmapDataCopy));
321 if (aSourceBitmap.iUid.iUid != KCBitwiseBitmapUid.iUid)
322 return KErrNotSupported;
323 const TDisplayMode displayMode = aSourceBitmap.iSettings.CurrentDisplayMode();
324 __ASSERT_DEBUG(iSettings.CurrentDisplayMode() == displayMode, ::Panic(EFbsPanicBitmapDataCopy));
325 if (aSourceBitmap.iHeader.iSizeInPixels.iWidth > 0)
326 iHeader.iSizeInTwips.iWidth = (aSourceBitmap.iHeader.iSizeInTwips.iWidth * iHeader.iSizeInPixels.iWidth)
327 / aSourceBitmap.iHeader.iSizeInPixels.iWidth;
328 if (aSourceBitmap.iHeader.iSizeInPixels.iHeight > 0)
329 iHeader.iSizeInTwips.iHeight = (aSourceBitmap.iHeader.iSizeInTwips.iHeight * iHeader.iSizeInPixels.iHeight)
330 / aSourceBitmap.iHeader.iSizeInPixels.iHeight;
331 TUint32* destBase = DataAddress();
332 TUint32* srcBase = aSourceBitmap.DataAddress();
333 if (!destBase || !srcBase)
335 TInt minPixelHeight = Min(iHeader.iSizeInPixels.iHeight, aSourceBitmap.iHeader.iSizeInPixels.iHeight);
336 if (aSourceBitmap.iIsCompressedInRAM)
338 TUint8* dest = (TUint8*)destBase;
339 TInt minPixelWidth = Min(iHeader.iSizeInPixels.iWidth, aSourceBitmap.iHeader.iSizeInPixels.iWidth);
340 TPtr8 pDest(dest, iByteWidth, iByteWidth);
342 TPoint ditherOffset(0, 0);
343 TLineScanningPosition scanPos(srcBase);
344 scanPos.iScanLineBuffer = HBufC8::New(aSourceBitmap.iByteWidth + 4);
345 if (!scanPos.iScanLineBuffer)
347 for (TInt row = 0; row < minPixelHeight; ++row)
349 pDest.Set(dest, iByteWidth, iByteWidth);
351 aSourceBitmap.GetScanLine(pDest, pt, minPixelWidth, EFalse, ditherOffset, displayMode, srcBase, scanPos);
354 delete scanPos.iScanLineBuffer;
358 TUint8* dest = (TUint8*)destBase;
359 TUint8* src = (TUint8*)srcBase;
360 TInt minByteWidth = Min(iByteWidth, aSourceBitmap.iByteWidth);
361 for(TInt row = 0; row < minPixelHeight; ++row)
363 Mem::Copy(dest, src, minByteWidth);
365 src += aSourceBitmap.iByteWidth;
368 if (iHeader.iSizeInPixels.iWidth > aSourceBitmap.iHeader.iSizeInPixels.iWidth)
370 TInt extraBits = (aSourceBitmap.iHeader.iSizeInPixels.iWidth * aSourceBitmap.iHeader.iBitsPerPixel) & 31;
373 TUint32 mask = KMaxTUint32;
375 TInt destWordWidth = iByteWidth >> 2;
376 TInt srcWordWidth = aSourceBitmap.iByteWidth >> 2;
377 TUint32* maskAddress = destBase + srcWordWidth - 1;
378 for (TInt row = 0; row < minPixelHeight; ++row)
380 *maskAddress |= mask;
381 maskAddress += destWordWidth;
388 EXPORT_C void CBitwiseBitmap::ExternalizeL(RWriteStream& aStream,const CFbsBitmap& aHandleBitmap) const
390 ExternalizeRectangleL(aStream,iHeader.iSizeInPixels,aHandleBitmap);
393 EXPORT_C void CBitwiseBitmap::ExternalizeRectangleL(RWriteStream& aStream,const TRect& aRect,const CFbsBitmap& aHandleBitmap) const
396 User::Leave(KErrArgument);
397 // the bitmap must have been already prepared for data access
398 if (aHandleBitmap.iUseCount == 0)
399 User::Leave(KErrArgument);
401 // If the bitmap is palette-compressed in RAM externalisation is currently not supported
402 // Externalisation of extended bitmaps is currently not supported either
403 if (iHeader.iCompression == EGenericPaletteCompression || iHeader.iCompression == EProprietaryCompression)
404 User::Leave(KErrNotSupported);
405 const TRect bitmapRect(iHeader.iSizeInPixels);
406 TRect sourceRect(aRect);
407 if (!sourceRect.Intersects(bitmapRect))
408 User::Leave(KErrTooBig);
409 sourceRect.Intersection(bitmapRect);
411 TDisplayMode displayMode = iSettings.CurrentDisplayMode();
412 const TInt scanLineByteLength = CBitwiseBitmap::ByteWidth(sourceRect.Width(),displayMode);
413 const TInt rectByteSize = sourceRect.Height() * scanLineByteLength;
414 TUint8* buffer = (TUint8*)User::AllocLC(scanLineByteLength);
416 TPtr8 scanline(buffer,scanLineByteLength,scanLineByteLength);
418 const TPoint zeroPoint;
419 TInt compressedSize = 0;
422 for (row = sourceRect.iTl.iY; row < sourceRect.iBr.iY; row++)
424 GetScanLine(scanline,TPoint(sourceRect.iTl.iX,row),sourceRect.Width(),EFalse,zeroPoint,displayMode,aHandleBitmap.DataAddress());
425 compressedSize += SizeOfDataCompressed(buffer,scanLineByteLength);
428 TBool compress = EFalse;
429 if(compressedSize > 0)
431 compress = (displayMode == EColor4K) || (compressedSize < (rectByteSize >> 1) + (rectByteSize >> 2));
434 aStream.WriteInt32L(sizeof(SEpocBitmapHeader) + ((compress) ? compressedSize : rectByteSize));
435 aStream.WriteInt32L(iHeader.iStructSize);
436 aStream.WriteInt32L(sourceRect.Width());
437 aStream.WriteInt32L(sourceRect.Height());
438 aStream.WriteInt32L(HorizontalPixelsToTwips(sourceRect.Width()));
439 aStream.WriteInt32L(VerticalPixelsToTwips(sourceRect.Height()));
440 aStream.WriteInt32L(iHeader.iBitsPerPixel);
441 aStream.WriteUint32L(iHeader.iColor);
442 aStream.WriteInt32L(0);
443 aStream.WriteUint32L(compress ? CompressionType(iHeader.iBitsPerPixel, iHeader.iColor) : ENoBitmapCompression);
445 for (row = sourceRect.iTl.iY; row < sourceRect.iBr.iY; row++)
447 GetScanLine(scanline,TPoint(sourceRect.iTl.iX,row),sourceRect.Width(),EFalse,zeroPoint,displayMode,aHandleBitmap.DataAddress());
450 aStream.WriteL(buffer,scanLineByteLength);
452 DoExternalizeDataCompressedL(aStream,buffer,scanLineByteLength);
455 CleanupStack::PopAndDestroy(); // buffer
458 EXPORT_C void CBitwiseBitmap::InternalizeHeaderL(RReadStream& aStream,SEpocBitmapHeader& aHeader)
460 aHeader.iBitmapSize=aStream.ReadInt32L();
461 aHeader.iStructSize=aStream.ReadInt32L();
462 if (aHeader.iStructSize!=sizeof(SEpocBitmapHeader)) User::Leave(KErrCorrupt);
463 aHeader.iSizeInPixels.iWidth=aStream.ReadInt32L();
464 aHeader.iSizeInPixels.iHeight=aStream.ReadInt32L();
465 aHeader.iSizeInTwips.iWidth=aStream.ReadInt32L();
466 aHeader.iSizeInTwips.iHeight=aStream.ReadInt32L();
467 aHeader.iBitsPerPixel=aStream.ReadInt32L();
468 aHeader.iColor=(TInt)aStream.ReadUint32L();
469 aHeader.iPaletteEntries=aStream.ReadInt32L();
470 if (aHeader.iPaletteEntries != 0)
472 //Palettes are not supported.
473 User::Leave(KErrNotSupported);
475 aHeader.iCompression=(TBitmapfileCompression)aStream.ReadUint32L();
476 CheckHeaderIsValidL(aHeader);
479 void CBitwiseBitmap::CheckHeaderIsValidL(const SEpocBitmapHeader& aHeader)
481 //These fields are signed in the structure?
482 TInt bitmapSize = aHeader.iBitmapSize;
483 TInt imageHeightPix = aHeader.iSizeInPixels.iHeight;
484 TInt imageWidthPix = aHeader.iSizeInPixels.iWidth;
485 TInt bitsPerPixel = aHeader.iBitsPerPixel;
486 TInt compression = aHeader.iCompression;
487 TInt colour = aHeader.iColor;
488 TBool corruptFlag = EFalse;
490 //Need to copy the values from the structure
491 TDisplayMode equivalentMode = CBitwiseBitmap::DisplayMode(aHeader.iBitsPerPixel,aHeader.iColor);
492 if (equivalentMode == ENone)
494 User::Leave(KErrNotSupported);
496 if(aHeader.iColor < 0)
500 //easieast way to check if compression type is appropriate is to ask the compressor
501 if (compression && compression!= CBitwiseBitmap::CompressionType(bitsPerPixel,colour))
505 //danger when using CBitwiseBitmap is they could panic for bad input...
506 if (imageHeightPix <= 0 || imageWidthPix <= 0 || bitsPerPixel <= 0)
510 const TInt KMeg = 1024 * 1024;
511 //Test that scanline bytes calculation won't overflow.
512 TInt bytesPerPack; // pixel size in memory
513 TInt bytesPerCompression; // compressed unit data size
514 User::LeaveIfError(CompressedFormatInfo(equivalentMode, bytesPerPack, bytesPerCompression));
515 if (imageWidthPix > 2047 * KMeg / bytesPerPack)
519 TInt uncompressedWidthBytes = CBitwiseBitmap::ByteWidth(imageWidthPix,equivalentMode); //we know this won't overflow, now.
520 //use top set bit indexes of 32 bit integer values to estimate when W*H multiply will overflow
521 TInt exponentWidth = 0;
522 TInt exponentHeight = 0;
523 if (uncompressedWidthBytes & 0xffff0000)
527 if (imageHeightPix & 0xffff0000)
529 exponentHeight += 16;
531 if (exponentWidth || exponentHeight)
533 if (uncompressedWidthBytes & 0xFF00FF00)
537 if (imageHeightPix & 0xFF00FF00)
541 if (uncompressedWidthBytes & 0xf0f0f0f0)
545 if (imageHeightPix & 0xf0f0f0f0)
549 if (uncompressedWidthBytes & 0xCCCCCCCC)
553 if (imageHeightPix & 0xCCCCCCCC)
557 if (uncompressedWidthBytes & 0xaaaaaaaa)
561 if (imageHeightPix & 0xaaaaaaaa)
565 TInt exponentTotal = exponentWidth + exponentHeight;
566 if (exponentTotal >= 31)
568 //The result would defuinitely exceed a signed int
571 else if (exponentTotal == 30)
573 //as a bit test, both "next most significat bits" must be set to cause a carry-over,
574 //but that isn't so trivial to test.
575 if ((uncompressedWidthBytes >> 1) * imageHeightPix > 1024 * KMeg)
583 /* estimate compressed file size limits
584 byte compression uses lead code 0..127 = repeat next byte n+1 times. -1..-128 = copy next -n bytes
585 16, 24, 32 use byte lead codes as above followed by words, triplets, or dwords
586 1,2,4,8,16 all encode any dword alignment buffer padding data as full data values.
587 32 doesn't have padding issue. 24 does not encode padding bytes.
588 12 bit compression uses 0..15 spare nibble to encode short runs. 0=unique. Can never make file bigger.*/
589 if (bitsPerPixel == 12)
591 //min file size is 1/16 of rect size
592 if (bitmapSize < sizeof(SEpocBitmapHeader) + ((uncompressedWidthBytes * imageHeightPix) / 16))
596 if (bitmapSize > sizeof(SEpocBitmapHeader) + uncompressedWidthBytes * imageHeightPix)
603 TInt packedValsPerFile = (uncompressedWidthBytes / bytesPerPack) * imageHeightPix;
604 //for some of the compressors 0 means a run of 2, so max 127 means a run of 129
605 TInt estMinCompressedBlocksPerFile = (packedValsPerFile - 1) / 129 + 1;
606 /* Absolute minimum is blocks of 128 repeats possibly spanning multiple scanlines
607 This can't be compressed by the current per-scanline compressor,
608 but is acceptable to the decompressor. */
609 if (bitmapSize < sizeof(SEpocBitmapHeader) + estMinCompressedBlocksPerFile * (bytesPerCompression + 1))
613 /* Absolute maximum is to store every pixel as a seperate run of 1 byte.
614 The current compressor would never do this... but the file is legal! */
615 if (bitmapSize > sizeof(SEpocBitmapHeader) + packedValsPerFile * (bytesPerCompression + 1))
623 if (bitmapSize != sizeof(SEpocBitmapHeader) + uncompressedWidthBytes * imageHeightPix)
630 User::Leave(KErrCorrupt);
636 Internalizes the bit map contents from a stream.
637 @param aStream The read stream containing the bit map.
639 EXPORT_C void CBitwiseBitmap::InternalizeL(RReadStream& aStream)
641 if (iHeap==NULL || iPile==NULL)
642 User::Leave(KErrNoMemory);
644 InternalizeHeaderL(aStream,iHeader);
646 TDisplayMode displayMode = DisplayMode(iHeader.iBitsPerPixel,iHeader.iColor);
647 if(displayMode == ENone)
650 User::Leave(KErrCorrupt);
653 iSettings.SetDisplayModes(displayMode);
655 iByteWidth = ByteWidth(iHeader.iSizeInPixels.iWidth,iSettings.CurrentDisplayMode());
658 TInt bytesize = iByteWidth * iHeader.iSizeInPixels.iHeight;
661 data = iPile->Alloc(bytesize);
662 iDataOffset = data - iPile->ChunkBase();
667 User::LeaveNoMemory();
670 TRAPD(err,DoInternalizeL(aStream,iHeader.iBitmapSize-iHeader.iStructSize,DataAddress()));
679 void CBitwiseBitmap::DoInternalizeL(RReadStream& aStream,TInt aSrceSize,TUint32* aBase)
681 if (iHeader.iCompression==ENoBitmapCompression)
682 aStream.ReadL((TUint8*)aBase,aSrceSize);
683 else if (iHeader.iCompression < ERLECompressionLast)
685 TBitmapfileCompression compression = iHeader.iCompression;
686 iHeader.iCompression = ENoBitmapCompression;
687 iHeader.iBitmapSize = iByteWidth*iHeader.iSizeInPixels.iHeight+sizeof(SEpocBitmapHeader);
688 DoInternalizeCompressedDataL(aStream,aSrceSize,aBase,compression);
691 CheckHeaderIsValidL(iHeader);
694 EXPORT_C TDisplayMode CBitwiseBitmap::DisplayMode() const
696 return iSettings.CurrentDisplayMode();
699 EXPORT_C TInt CBitwiseBitmap::HorizontalPixelsToTwips(TInt aPixels) const
701 if (iHeader.iSizeInPixels.iWidth==0)
704 twips = (aPixels*iHeader.iSizeInTwips.iWidth+(iHeader.iSizeInPixels.iWidth/2))/iHeader.iSizeInPixels.iWidth;
708 EXPORT_C TInt CBitwiseBitmap::VerticalPixelsToTwips(TInt aPixels) const
710 if (iHeader.iSizeInPixels.iHeight==0)
713 twips = (aPixels*iHeader.iSizeInTwips.iHeight+(iHeader.iSizeInPixels.iHeight/2))/iHeader.iSizeInPixels.iHeight;
717 EXPORT_C TSize CBitwiseBitmap::SizeInPixels() const
719 return(iHeader.iSizeInPixels);
722 EXPORT_C TSize CBitwiseBitmap::SizeInTwips() const
724 return(iHeader.iSizeInTwips);
727 EXPORT_C TInt CBitwiseBitmap::HorizontalTwipsToPixels(TInt aTwips) const
729 if (iHeader.iSizeInTwips.iWidth==0)
732 pixels = (aTwips*iHeader.iSizeInPixels.iWidth+(iHeader.iSizeInTwips.iWidth/2))/iHeader.iSizeInTwips.iWidth;
736 EXPORT_C TInt CBitwiseBitmap::VerticalTwipsToPixels(TInt aTwips) const
738 if (iHeader.iSizeInTwips.iHeight==0)
741 pixels = (aTwips*iHeader.iSizeInPixels.iHeight+(iHeader.iSizeInTwips.iHeight/2))/iHeader.iSizeInTwips.iHeight;
746 The method retrieves the red, green, blue (RGB) color value of the pixel with
747 specified coordinates.
748 Note: The method works for uncompressed bitmaps and extended bitmaps only.
752 @param aColor It will be initialized with the pixel color value on success, otherwise
753 aColor value will be left unchanged.
754 @param aPixel Pixel coordinates.
755 @param aBase It points to the beginning of the bitmap data.
757 EXPORT_C void CBitwiseBitmap::GetPixel(TRgb& aColor,const TPoint& aPixel,TUint32* aBase, CFbsRasterizer* aRasterizer) const
759 // This operation is not currently supported for compressed bitmaps.
760 if (iHeader.iCompression != ENoBitmapCompression && iHeader.iCompression != EProprietaryCompression)
762 __ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
768 TInt x=aPixel.iX,y=aPixel.iY;
769 if (x < -iHeader.iSizeInPixels.iWidth)
770 x %= iHeader.iSizeInPixels.iWidth;
771 if (y < -iHeader.iSizeInPixels.iHeight)
772 y %= iHeader.iSizeInPixels.iHeight;
774 x += iHeader.iSizeInPixels.iWidth;
776 y += iHeader.iSizeInPixels.iHeight;
778 if (iHeader.iCompression == EProprietaryCompression)
782 TUint32* slptr = const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(x,y), 1));
785 aColor = GetRgbPixelEx(x, slptr);
789 // wrong rasterizer for this extended bitmap - return white pixel
795 // no rasterizer - return white pixel
801 aColor = GetRgbPixelEx(x,ScanLineAddress(aBase,y));
805 EXPORT_C TInt CBitwiseBitmap::GetScanLinePtr(TUint32*& aSlptr, TInt& aLength,TPoint& aPixel,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
809 if (aPixel.iX >= iHeader.iSizeInPixels.iWidth || aPixel.iX < -iHeader.iSizeInPixels.iWidth)
810 aPixel.iX %= iHeader.iSizeInPixels.iWidth;
811 if (aPixel.iY >= iHeader.iSizeInPixels.iHeight || aPixel.iY < -iHeader.iSizeInPixels.iHeight)
812 aPixel.iY %= iHeader.iSizeInPixels.iHeight;
814 aPixel.iX += iHeader.iSizeInPixels.iWidth;
816 aPixel.iY += iHeader.iSizeInPixels.iHeight;
817 if (aPixel.iX + aLength > iHeader.iSizeInPixels.iWidth)
818 aLength = iHeader.iSizeInPixels.iWidth - aPixel.iX;
819 if (iHeader.iCompression != ENoBitmapCompression)
821 return DoGetScanLinePtr(aSlptr, aPixel,aLength,aBase,aLineScanningPosition);
825 aSlptr = ScanLineAddress(aBase,aPixel.iY);
830 EXPORT_C TInt CBitwiseBitmap::GetScanLinePtr(TUint32*& aSlptr, TPoint& aPixel,TInt aLength,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
832 return GetScanLinePtr(aSlptr, aLength,aPixel,aBase, aLineScanningPosition);
835 TUint8 CBitwiseBitmap::GetGrayPixelEx(TInt aX,TUint32* aScanlinePtr) const
837 // returns pixel as EGray256 value (0 - 255)
840 return TUint8(GetRgbPixelEx(aX,aScanlinePtr)._Gray256());
846 if (aX >= iHeader.iSizeInPixels.iWidth)
847 aX %= iHeader.iSizeInPixels.iWidth;
849 switch (iHeader.iBitsPerPixel)
853 TUint32 col = *(aScanlinePtr+(aX>>4));
856 col |= (col << 6) | (col<<4) | (col<<2);
861 TUint32 col = *(aScanlinePtr+(aX>>3));
864 return TUint8(col |= (col << 4));
868 TUint32 col = *(aScanlinePtr+(aX>>5));
869 if (col&(1<<(aX&0x1f))) return 255 ;
873 return *(((TUint8*)aScanlinePtr) + aX);
881 TRgb CBitwiseBitmap::GetRgbPixelEx(TInt aX,TUint32* aScanlinePtr) const
883 // returns pixel as TRgb
890 if (aX>=iHeader.iSizeInPixels.iWidth)
891 aX%=iHeader.iSizeInPixels.iWidth;
893 switch (iHeader.iBitsPerPixel)
896 if (iSettings.CurrentDisplayMode() == EColor16MAP)
897 return TRgb::_Color16MAP(*(aScanlinePtr + aX));
898 else if (iSettings.CurrentDisplayMode() == EColor16MA)
899 return TRgb::_Color16MA(*(aScanlinePtr + aX));
900 //scanLineBytePointer format: BGR0 - 0RGB as INT32.
902 return TRgb::_Color16MU(*(aScanlinePtr + aX));
905 TUint8* scanLineBytePointer = (TUint8*)aScanlinePtr + aX * 3;
906 TInt color16M = *scanLineBytePointer++;
907 color16M |= (*scanLineBytePointer++) << 8;
908 color16M |= (*scanLineBytePointer++) << 16;
909 return TRgb::_Color16M(color16M);
912 return TRgb::_Color64K(*(((TUint16*)aScanlinePtr) + aX));
914 return TRgb::_Color4K(*(((TUint16*)aScanlinePtr) + aX));
916 return TRgb::Color256(*((TUint8*)aScanlinePtr + aX));
919 TUint8 colorIndex = *((TUint8*)aScanlinePtr + (aX >> 1));
922 return TRgb::Color16(colorIndex & 0xf);
929 return TRgb::_Gray256(GetGrayPixelEx(aX,aScanlinePtr));
932 void CBitwiseBitmap::GetRgbPixelExMany(TInt aX,TUint32* aScanlinePtr, TUint32* aDest,TInt aLength) const
934 __ASSERT_DEBUG(aScanlinePtr && aDest, User::Invariant());
935 __ASSERT_DEBUG(aX >= 0, User::Invariant());
936 __ASSERT_DEBUG(aLength >= 0, User::Invariant());
937 __ASSERT_DEBUG(aX+aLength <= iHeader.iSizeInPixels.iWidth, User::Invariant());
946 const TUint32 opaqueAlpha = 0xff000000;
947 TUint32 color16MA = 0; // // cached map to color
956 switch (iHeader.iBitsPerPixel)
960 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr);
961 TUint32 color16 = EFirstTime; // map source color: 16 color mode
964 rawData = (aX & 1) ? (scanPtr8[aX >> 1] >> 4) : (scanPtr8[aX >> 1] &0x0F);
965 if ((rawData != color16))
966 { // first pixel or colour change
967 color16MA = TRgb::Color16(rawData)._Color16MA();
970 *aDest++ = color16MA;
978 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
979 const TUint32* lookup = DynamicPalette::DefaultColor256Util()->iColorTable;
980 TUint32 color256 = EFirstTime; // map source color: 256 color
983 rawData = *scanPtr8++;
984 if ((rawData != color256))
985 { // colour change or first pixel
986 color16MA = lookup[rawData];
988 // translate between bgr & rgb
989 color16MA = ((color16MA & 0x0000ff) << 16) | (color16MA & 0x00ff00) | ((color16MA & 0xff0000) >> 16) | opaqueAlpha;
991 *aDest++ = color16MA;
998 scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
999 TUint32 color4K = EFirstTime; // map source color: 4K color black => 16M color black
1002 rawData = *scanPtr16++;
1003 if ((rawData != color4K))
1005 color16MA = TRgb::_Color4K(rawData)._Color16MA();
1008 *aDest++ = color16MA;
1015 scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
1016 const TUint16* lowAdd = Convert16to32bppLow();
1017 const TUint32* highAdd = Convert16to32bppHigh();
1018 TUint32 color64K = EFirstTime; // map source color: 64K color black => 16M color black
1021 rawData = *scanPtr16++;
1022 if ((rawData != color64K))
1024 color16MA = highAdd[rawData >> 8] | lowAdd[rawData & 0x00FF];
1027 *aDest++ = color16MA;
1034 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX*3;
1037 if ((aLength < 4) || (3 & (TUint32)(scanPtr8)))
1040 color = *scanPtr8++;
1041 color |= (*scanPtr8++) << 8;
1042 color |= (*scanPtr8++) << 16;
1043 *aDest++ = color | opaqueAlpha;
1046 { // source is now TUint32 aligned - so read source as blocks of 3 TUint32's & write as 4
1047 TUint32 word1, word2, word3;
1048 TInt iter = (aLength / 4) - 1;
1049 aLength = aLength & 0x0003;
1052 word1 = *scanPtr32++;
1053 *aDest++ = word1 | opaqueAlpha;
1054 word2 = *scanPtr32++;
1055 color = (word1 >> 24) | ((word2 & 0xFFFF) << 8);
1056 *aDest++ = color | opaqueAlpha;
1057 word3 = *scanPtr32++;
1058 color = (word2 >> 16) | ((word3 & 0x00FF) << 16);
1059 *aDest++ = color | opaqueAlpha;
1060 *aDest++ = (word3 >> 8) | opaqueAlpha;
1070 scanPtr32 = aScanlinePtr + aX;
1071 if(iSettings.CurrentDisplayMode() == EColor16MAP)
1072 { // unrolled loop uses "Duff's Device"
1073 const TUint16* normTable = PtrTo16BitNormalisationTable();
1075 TInt iter = aLength / 8;
1080 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
1082 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
1084 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
1086 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
1088 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
1090 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
1092 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
1094 *aDest++ = PMA2NonPMAPixel(*scanPtr32++, normTable);
1095 } while (iter-- > 0);
1098 else if (iSettings.CurrentDisplayMode() == EColor16MU)
1099 { // unrolled loop uses "Duff's Device"
1101 TInt iter = aLength / 8;
1106 *aDest++ = (*scanPtr32++) | opaqueAlpha;
1108 *aDest++ = (*scanPtr32++) | opaqueAlpha;
1110 *aDest++ = (*scanPtr32++) | opaqueAlpha;
1112 *aDest++ = (*scanPtr32++) | opaqueAlpha;
1114 *aDest++ = (*scanPtr32++) | opaqueAlpha;
1116 *aDest++ = (*scanPtr32++) | opaqueAlpha;
1118 *aDest++ = (*scanPtr32++) | opaqueAlpha;
1120 *aDest++ = (*scanPtr32++) | opaqueAlpha;
1121 } while (iter-- > 0);
1126 Mem::Move(aDest, scanPtr32, aLength * 4);
1136 switch (iHeader.iBitsPerPixel)
1142 *aDest++ = TUint32(COLOR_VALUE(aScanlinePtr, aX) ? 0xFFFFFFFF : 0xFF000000);
1150 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
1153 rawData = *scanPtr8++;
1154 color16MA = rawData | (rawData << 8) | (rawData << 16) | opaqueAlpha;
1155 *aDest++ = color16MA;
1164 rawData = GetGrayPixelEx(aX++,aScanlinePtr);
1165 color16MA = rawData | (rawData << 8) | (rawData << 16) | opaqueAlpha;
1166 *aDest++ = color16MA;
1174 The method retrieves the RGB color values from the scanline, and converts them
1175 into the destination screen-mode pixel format. This method handles the special
1176 case when the destination mode is EColor16MAP (32bit with alpha values premultiplied
1177 with the color channels. Calls GetRgbPixelExMany for values not 32 bit, as there is no
1178 alpha information in these color modes. For color mode EColor16MU, no conversion is
1179 performed (as alpha is assumed to be 1).
1182 @param aX The x co-ordinate the scanline data needs to be retrieved from.
1183 @param aScanlinePtr The scanline pointer, i.e. the source data.
1184 @param aDest The pointer to the destination buffer. This is where the output is stored.
1185 @param aLength The number of bytes to be copied. This value must be a multiple of 4.
1187 void CBitwiseBitmap::GetRgbPixelExMany16MAP(TInt aX,TUint32* aScanlinePtr,TUint32* aDest,TInt aLength) const
1189 __ASSERT_DEBUG(aScanlinePtr && aDest, User::Invariant());
1190 __ASSERT_DEBUG(aX >= 0, User::Invariant());
1191 __ASSERT_DEBUG(aLength >= 0, User::Invariant());
1192 __ASSERT_DEBUG(aX+aLength <= iHeader.iSizeInPixels.iWidth, User::Invariant());
1196 if ((iHeader.iColor) && (iHeader.iBitsPerPixel == 32))
1198 scanPtr32 = aScanlinePtr + aX;
1199 if (DisplayMode() == EColor16MAP)
1201 Mem::Move(aDest, scanPtr32, aLength<<2);
1203 else if(DisplayMode()==EColor16MA)
1205 TUint32* ptrLimit = aDest + aLength;
1206 const TInt32 zero = 0;
1207 while (aDest < ptrLimit)
1209 TUint32 value = *scanPtr32++;
1210 TUint32 tA = value >> 24;
1217 *aDest++ = NonPMA2PMAPixel(value);
1225 else // DisplayMode() == EColor16MU
1228 { // unrolled loop uses "Duff's Device"
1229 const TUint32 alpha = 0xFF000000; //set all the alpha to 0xff
1230 TInt iter = aLength / 8;
1235 *aDest++ = (*scanPtr32++) | alpha;
1237 *aDest++ = (*scanPtr32++) | alpha;
1239 *aDest++ = (*scanPtr32++) | alpha;
1241 *aDest++ = (*scanPtr32++) | alpha;
1243 *aDest++ = (*scanPtr32++) | alpha;
1245 *aDest++ = (*scanPtr32++) | alpha;
1247 *aDest++ = (*scanPtr32++) | alpha;
1249 *aDest++ = (*scanPtr32++) | alpha;
1250 } while (iter-- > 0);
1257 GetRgbPixelExMany(aX, aScanlinePtr, aDest, aLength);
1261 void CBitwiseBitmap::GetRgbPixelExMany16M(TInt aX,TUint32* aScanlinePtr, TUint8* aDest,TInt aLength) const
1277 const TUint32 zero = 0; // conveniently KRgbBlack is 0 in EColor16M mode
1280 if ((aLength < 4) || (3 & (TUint32)(destPtr8)))
1288 { // dest is now TUint32 aligned - write 4 pixels into 3 TUint32s
1290 *destPtr32++ = zero;
1291 *destPtr32++ = zero;
1292 *destPtr32++ = zero;
1298 if (aX>=iHeader.iSizeInPixels.iWidth)
1300 aX%=iHeader.iSizeInPixels.iWidth;
1305 // cached map to color
1306 TUint32 color16M = 0;
1307 TInt copyLength = iHeader.iSizeInPixels.iWidth - aX;
1308 TUint32* scanPtr32 = aScanlinePtr + aX;
1309 if (copyLength > aLength)
1311 copyLength = aLength;
1313 aLength -= copyLength;
1317 switch(iHeader.iBitsPerPixel)
1321 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr);
1322 TUint32 color16 = EFirstTime; // map source color: 16 color mode
1325 rawData = (aX & 1) ? (scanPtr8[aX >> 1] >> 4) : (scanPtr8[aX >> 1] &0x0F);
1326 if ((rawData != color16))
1327 { // first pixel or colour change
1328 color16M = TRgb::Color16(rawData)._Color16M();
1331 *destPtr8++ = TUint8(color16M);
1332 *destPtr8++ = TUint8(color16M >> 8);
1333 *destPtr8++ = TUint8(color16M >> 16);
1336 while (--copyLength);
1341 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
1342 const TUint32* lookup = DynamicPalette::DefaultColor256Util()->iColorTable;
1343 TUint32 color256 = EFirstTime; // map source color: 256 color
1346 rawData = *scanPtr8++;
1347 if ((rawData != color256))
1348 { // first pixel or colour change; so perform new mapping
1349 color16M = lookup[rawData];
1352 // Note; byte order performs required bgr -> rgb conversion
1353 *destPtr8++ = TUint8(color16M >> 16);
1354 *destPtr8++ = TUint8(color16M >> 8);
1355 *destPtr8++ = TUint8(color16M);
1357 while (--copyLength);
1362 scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
1363 TUint32 color4K = EFirstTime; // map source color: 4K color black => 16M color black
1366 rawData = *scanPtr16++;
1367 if ((rawData != color4K))
1368 { // first pixel or colour change
1369 color16M = TRgb::_Color4K(rawData)._Color16M();
1372 *destPtr8++ = TUint8(color16M);
1373 *destPtr8++ = TUint8(color16M >> 8);
1374 *destPtr8++ = TUint8(color16M >> 16);
1376 while (--copyLength);
1381 scanPtr16 = reinterpret_cast<TUint16*>(aScanlinePtr) + aX;
1382 const TUint16* lowAdd = Convert16to32bppLow();
1383 const TUint32* highAdd = Convert16to32bppHigh();
1385 TUint32 color64K = EFirstTime; // 64K color black => 16M color black
1389 halfWord = *scanPtr16++;
1390 if ((halfWord != color64K))
1392 color16M = highAdd[halfWord >> 8] | lowAdd[halfWord & 0x00FF];
1393 color64K = halfWord;
1395 *destPtr8++ = TUint8(color16M);
1396 *destPtr8++ = TUint8(color16M >> 8);
1397 *destPtr8++ = TUint8(color16M >> 16);
1399 while (--copyLength);
1404 Mem::Copy(destPtr8, reinterpret_cast<TUint8*>(aScanlinePtr) + aX, copyLength * 3); // may not be aligned
1405 destPtr8 += copyLength * 3;
1410 scanPtr32 = aScanlinePtr + aX;
1411 if (iSettings.CurrentDisplayMode() == EColor16MAP)
1413 const TUint16* normTable = PtrTo16BitNormalisationTable();
1416 // convert from EColor16MAP to EColor16MA first.
1417 color16M = PMA2NonPMAPixel(*scanPtr32++, normTable);
1418 *destPtr8++ = TUint8(color16M);
1419 *destPtr8++ = TUint8(color16M >> 8);
1420 *destPtr8++ = TUint8(color16M >> 16);
1422 while (--copyLength);
1425 { // EColor16MA or EColor16MU, keep the RGB & throw away the top byte
1426 // scanLineBytePointer format: ARGB - 0RGB as INT32 or BGR0 - 0RGB as INT32.
1429 if ((copyLength < 4) || (3 & (TUint32)destPtr8))
1431 color16M = *scanPtr32++;
1433 *destPtr8++ = TUint8(color16M);
1434 *destPtr8++ = TUint8(color16M >> 8);
1435 *destPtr8++ = TUint8(color16M >> 16);
1437 else // dest is TUint32 aligned: copy 4 pixels into 3 TUint32's
1439 color16M = (*scanPtr32++) & 0x00FFFFFF;
1440 rawData = (*scanPtr32++) & 0x00FFFFFF;
1442 *destPtr32++ = color16M | (rawData << 24);
1443 color16M = (*scanPtr32++) & 0x00FFFFFF;
1444 *destPtr32++ = (color16M << 16) | (rawData >> 8);
1445 rawData = (*scanPtr32++) & 0x00FFFFFF;
1446 *destPtr32++ = (color16M >> 16) | (rawData << 8);
1458 { // !iHeader.iColor
1459 if (iHeader.iBitsPerPixel == 8)
1461 scanPtr8 = reinterpret_cast<TUint8*>(aScanlinePtr) + aX;
1464 rawData = *scanPtr8++;
1465 *destPtr8++ = (TUint8)rawData;
1466 *destPtr8++ = (TUint8)rawData;
1467 *destPtr8++ = (TUint8)rawData;
1469 while (--copyLength);
1475 rawData = GetGrayPixelEx(aX++,aScanlinePtr);
1476 *destPtr8++ = (TUint8)rawData;
1477 *destPtr8++ = (TUint8)rawData;
1478 *destPtr8++ = (TUint8)rawData;
1480 while (--copyLength);
1483 aX = 0; // second copy, if any, comes from start of line
1489 void CBitwiseBitmap::GenerateLineFromCompressedEightBitData(TUint8* aDestBuffer, const TPoint& aPixel,TInt aLength, TUint32* aBase,TLineScanningPosition& aLineScanningPosition) const
1491 const TInt bitmapWidth=iByteWidth;
1492 const TInt pixelsPerByte=8/iHeader.iBitsPerPixel;
1493 const TInt startPos=aPixel.iY*bitmapWidth+aPixel.iX/pixelsPerByte;
1494 const TInt endPos=aPixel.iY*bitmapWidth+(aPixel.iX+aLength+pixelsPerByte-1)/pixelsPerByte;
1495 const TInt byteLength=endPos-startPos;
1496 TInt writes=byteLength;
1497 TUint8* destPtr = ((TUint8*)aDestBuffer);
1498 destPtr+=(aPixel.iX/pixelsPerByte);
1499 if (aLineScanningPosition.iCursorPos>startPos)
1501 aLineScanningPosition.iSrcDataPtr=(TUint8*)aBase;
1502 aLineScanningPosition.iCursorPos=0;
1504 TUint8* srcePtr = (TUint8*)aLineScanningPosition.iSrcDataPtr;
1505 TInt8 count=*srcePtr;
1508 addition=(TInt16) (-count);
1510 addition=(TInt16) (count+1);
1511 while (aLineScanningPosition.iCursorPos+addition<startPos)
1513 aLineScanningPosition.iCursorPos+=addition;
1516 srcePtr+=(-count+1);
1520 srcePtr+=2; // Just skip over value
1524 addition=(TInt16) (-count);
1526 addition=(TInt16) (count+1);
1528 // Then scan the line
1530 while (aLineScanningPosition.iCursorPos+count<startPos+byteLength)
1532 TBool negativeCount=EFalse;
1536 negativeCount=ETrue;
1537 count=(TInt8) ((-count)-1);
1539 TUint8 value = *(srcePtr+1);
1540 TInt distanceToTheLineEnd=startPos+byteLength-aLineScanningPosition.iCursorPos;
1541 if (count<distanceToTheLineEnd)
1551 TInt countPlusOne = (TInt)count + 1;
1552 TInt start = Max(0,startPos-aLineScanningPosition.iCursorPos);
1553 if (countPlusOne > start)
1555 TInt length = Min(countPlusOne-start,writes);
1556 writes -= countPlusOne-start;
1559 /*Mem::Fill and Mem::Copy used in order to increase the performance*/
1562 Mem::Fill(destPtr,length,value);
1566 Mem::Copy(destPtr,srcePtr+start,length);
1573 srcePtr += countPlusOne;
1575 aLineScanningPosition.iCursorPos += countPlusOne;
1581 if (aLineScanningPosition.iCursorPos<startPos)
1583 correction=startPos-aLineScanningPosition.iCursorPos+1;
1585 TInt length = Min(byteLength,writes);
1587 /*Mem::Fill and Mem::Copy used in order to increase the performance*/
1590 Mem::Fill(destPtr,length,value);
1594 Mem::Copy(destPtr,srcePtr+correction,length);
1599 aLineScanningPosition.iSrcDataPtr=(TUint8*) srcePtr;
1602 void CBitwiseBitmap::GenerateLineFromCompressedTwelveBitData(TUint8* aDestBuffer, const TPoint& aPixel,TInt aLength, TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
1604 const TInt bitmapWidth=iByteWidth>>1;
1605 const TInt startPos=aPixel.iY*bitmapWidth+aPixel.iX;
1606 TInt writes=aLength*2;
1607 TUint16* destPtr = ((TUint16*)aDestBuffer);//+aPixel.iX;
1612 ::AdjustLineScanningPosition(aLineScanningPosition, aBase, bitmapWidth, startPos, iHeader.iBitmapSize - sizeof(SEpocBitmapHeader));
1614 TUint16* srcePtr = (TUint16*)aLineScanningPosition.iSrcDataPtr;
1616 // Fast find the correct position to start
1618 if(::Abs(aLineScanningPosition.iCursorPos - startPos) > startPos)
1620 srcePtr = (TUint16*)aBase;
1621 aLineScanningPosition.iCursorPos = 0;
1623 while (aLineScanningPosition.iCursorPos>startPos)
1626 TUint16 value = *srcePtr;
1627 count = value >> 12;
1628 aLineScanningPosition.iCursorPos-=(count+1);
1630 while (aLineScanningPosition.iCursorPos<startPos)
1632 TUint16 value = *srcePtr++;
1633 count = value >> 12;
1634 aLineScanningPosition.iCursorPos+=count+1;
1636 if (aLineScanningPosition.iCursorPos>startPos)
1638 aLineScanningPosition.iCursorPos-=(count+1);
1642 // Then scan the line
1644 while (aLineScanningPosition.iCursorPos+count<startPos+aLength)
1646 TUint16 value = *srcePtr;
1647 count = value >> 12;
1649 TInt distanceToTheLineEnd=startPos+aLength-aLineScanningPosition.iCursorPos;
1650 if (count<distanceToTheLineEnd)
1653 for (TInt ii=0 ; ii<=count ; ii++)
1655 if (aLineScanningPosition.iCursorPos>=startPos)
1661 aLineScanningPosition.iCursorPos++;
1668 for (TInt ii=0 ; ii<distanceToTheLineEnd ; ii++)
1677 aLineScanningPosition.iSrcDataPtr=(TUint8*) srcePtr;
1681 The method generates a line from compressed 16 bpp bitmap data.
1683 @see TScanLineDecompressor
1685 void CBitwiseBitmap::GenerateLineFromCompressedSixteenBitData(TUint8* aDestBuffer,
1686 const TPoint& aPixel,
1689 TLineScanningPosition& aLineScanningPosition) const
1691 TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
1692 TScanLineDecompressor<E2bpp, E2bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
1693 decompr(aDestBuffer, aPixel, aLineScanningPosition, iByteWidth, iByteWidth, aLength);
1697 The method generates a line from compressed 24 bpp bitmap data.
1699 @see TScanLineDecompressor
1701 void CBitwiseBitmap::GenerateLineFromCompressed24BitData(
1702 TUint8* aDestBuffer,
1703 const TPoint& aPixel,
1706 TLineScanningPosition& aLineScanningPosition) const
1708 TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
1709 TScanLineDecompressor<E3bpp, E3bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
1710 decompr(aDestBuffer, aPixel, aLineScanningPosition, iByteWidth, iByteWidth, aLength);
1714 The method generates a line from compressed 24 bpp to 32 bpp bitmap data .
1716 @see TScanLineDecompressor
1718 void CBitwiseBitmap::GenerateLineFromCompressed32UBitData(
1719 TUint8* aDestBuffer,
1720 const TPoint& aPixel,
1723 TLineScanningPosition& aLineScanningPosition) const
1725 TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
1726 TScanLineDecompressor<E3bpp, E4bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
1728 TUint32 theByteWidthSrc = iHeader.iSizeInPixels.iWidth * 3;
1729 decompr(aDestBuffer, aPixel, aLineScanningPosition, theByteWidthSrc, iByteWidth, aLength);
1733 The method generates a line from compressed 32 bpp to 32 bpp bitmap data .
1735 @see TScanLineDecompressor
1737 void CBitwiseBitmap::GenerateLineFromCompressed32ABitData(
1738 TUint8* aDestBuffer,
1739 const TPoint& aPixel,
1742 TLineScanningPosition& aLineScanningPosition) const
1744 TInt comprDataBytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
1745 TScanLineDecompressor<E4bpp, E4bpp> decompr(aBase, comprDataBytes, iPile!=NULL);
1747 TUint32 theByteWidthSrc = iHeader.iSizeInPixels.iWidth * 4;
1748 decompr(aDestBuffer, aPixel, aLineScanningPosition, theByteWidthSrc, iByteWidth, aLength);
1751 TInt CBitwiseBitmap::DoGetScanLinePtr(TUint32*& aSlptr, TPoint& aPixel,TInt aLength,TUint32* aBase, TLineScanningPosition& aLineScanningPosition) const
1754 HBufC8* hBuf=aLineScanningPosition.iScanLineBuffer;
1757 RFbsSession* session=RFbsSession::GetSession();
1760 hBuf=session->GetScanLineBuffer();
1765 return KErrSessionClosed;
1767 aLineScanningPosition.iScanLineBuffer=hBuf;
1769 __ASSERT_ALWAYS(hBuf && hBuf->Des().MaxLength() >= iByteWidth, User::Invariant());
1770 buf = const_cast<TUint8*>(hBuf->Ptr());
1771 switch(iHeader.iCompression)
1773 case ETwelveBitRLECompression:
1774 GenerateLineFromCompressedTwelveBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
1776 case EByteRLECompression:
1777 GenerateLineFromCompressedEightBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
1779 case ESixteenBitRLECompression:
1780 GenerateLineFromCompressedSixteenBitData(buf, aPixel,aLength, aBase, aLineScanningPosition);
1782 case ETwentyFourBitRLECompression:
1783 GenerateLineFromCompressed24BitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
1785 case EThirtyTwoUBitRLECompression:
1786 GenerateLineFromCompressed32UBitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
1788 case EThirtyTwoABitRLECompression:
1789 GenerateLineFromCompressed32ABitData(buf, aPixel, aLength, aBase, aLineScanningPosition);
1791 case EGenericPaletteCompression:
1792 GenerateLineFromPaletteCompressedData(buf, aPixel, aLength, aBase, aLineScanningPosition);
1794 case EProprietaryCompression:
1795 if (aLineScanningPosition.iRasterizer)
1797 aSlptr = const_cast<TUint32*>(aLineScanningPosition.iRasterizer->ScanLine(Extra()->iSerialNumber, aPixel, aLength));
1803 WhiteFill(buf, iByteWidth, iSettings.CurrentDisplayMode());
1807 __ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
1808 return KErrNotSupported;
1811 aSlptr = (TUint32*) buf;
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
1820 TPoint pixel(aPixel);
1821 TUint32* slptr=NULL;
1822 GetScanLinePtr(slptr, aLength, pixel,aBase, aLineScanningPosition);
1823 GetScanLine(slptr,aBuf,pixel,aLength,aDither,aDitherOffset,aDispMode);
1826 EXPORT_C void CBitwiseBitmap::GetScanLine(TUint32*& aScanLinePtr, TDes8& aDestBuf,const TPoint& aPixel,TInt aLength,TBool aDither,
1827 const TPoint& aDitherOffset,TDisplayMode aDestinationDispMode) const
1831 TDisplayMode currentDisplayMode = iSettings.CurrentDisplayMode();
1832 if (!aScanLinePtr) // if scanline pointer is null,
1834 WhiteFill((TUint8*)aDestBuf.Ptr(),aDestBuf.MaxLength(),currentDisplayMode);
1837 TUint8* ptr = (TUint8*)aDestBuf.Ptr();
1838 // if dest pointer is not aligned
1839 if (!(TUint32(ptr)&3) && aDestinationDispMode == currentDisplayMode)
1841 if (iHeader.iBitsPerPixel < 8)
1842 GetScanLineExBits(aDestBuf,aPixel.iX,aLength,aScanLinePtr);
1844 GetScanLineExBytes(aDestBuf,aPixel.iX,aLength,aScanLinePtr);
1847 //read the scanline in destination display format.
1848 switch (aDestinationDispMode)
1851 GetScanLineGray2(aDestBuf,aPixel,aLength,aDither,aDitherOffset,aScanLinePtr);
1854 GetScanLineGray4(aDestBuf,aPixel,aLength,aDither,aDitherOffset,aScanLinePtr);
1857 GetScanLineGray16(aDestBuf,aPixel,aLength,aScanLinePtr);
1860 GetScanLineGray256(aDestBuf,aPixel,aLength,aScanLinePtr);
1863 GetScanLineColor16(aDestBuf,aPixel,aLength,aScanLinePtr);
1866 GetScanLineColor256(aDestBuf,aPixel,aLength,aScanLinePtr);
1869 GetScanLineColor4K(aDestBuf,aPixel,aLength,aScanLinePtr);
1872 GetScanLineColor64K(aDestBuf,aPixel,aLength,aScanLinePtr);
1875 GetScanLineColor16M(aDestBuf,aPixel,aLength,aScanLinePtr);
1878 GetScanLineColorRgb(aDestBuf,aPixel,aLength,aScanLinePtr);
1881 GetScanLineColor16MU(aDestBuf,aPixel,aLength,aScanLinePtr);
1884 GetScanLineColor16MA(aDestBuf,aPixel,aLength,aScanLinePtr);
1887 GetScanLineColor16MAP(aDestBuf,aPixel,aLength,aScanLinePtr);
1890 aDestBuf.SetLength(0);
1895 EXPORT_C void CBitwiseBitmap::GetScanLine(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase) const
1897 TLineScanningPosition pos(aBase);
1898 TUint8* base = REINTERPRET_CAST(TUint8*,aBase);
1899 const TCompressionBookMark* bookMarkPtr = NULL;
1901 GetLineScanPos(pos, bookMarkPtr, base);
1902 GetScanLine(aBuf,aPixel,aLength,aDither,aDitherOffset,aDispMode,aBase,pos);
1903 UpdateBookMark(pos, const_cast<TCompressionBookMark*>(bookMarkPtr), base);
1907 Gets the bitmap’s vertical scanline starting at the specified x co-ordinate and using
1908 the specified dither offset.
1909 Note: The method works for uncompressed bitmaps only.
1910 @param aBuf The buffer in which the vertical scanline will be returned.
1911 @param aX The x co-ordinate of the vertical scanline to get.
1912 @param aDitherOffset The dither offset of the bitmap.
1913 @param aDispMode Format to be used to write the data to the buffer.
1914 @param aBase The bitmap's data start address.
1916 EXPORT_C void CBitwiseBitmap::GetVerticalScanLine(TDes8& aBuf,TInt aX,TBool aDither,
1917 const TPoint& aDitherOffset,
1918 TDisplayMode aDispMode,
1920 CFbsRasterizer* aRasterizer) const
1922 if (iHeader.iCompression != ENoBitmapCompression && iHeader.iCompression != EProprietaryCompression)
1924 __ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
1925 return; //not supported for compressed bitmaps
1933 TInt height=iHeader.iSizeInPixels.iHeight;
1934 TUint32* slptr=aBase;
1935 TUint8* ptr = (TUint8*)aBuf.Ptr();
1937 const TInt wordwidth=iByteWidth>>2;
1940 if (iHeader.iCompression == EProprietaryCompression)
1944 slptr = const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,0), 1));
1947 // wrong rasterizer for this extended bitmap - fill vertical scan line with white pixels
1948 TInt bufLength = ByteWidth(height, aDispMode);
1949 aBuf.SetLength(bufLength);
1950 WhiteFill(ptr, bufLength, aDispMode);
1956 // no rasterizer - fill vertical scan line with white pixels
1957 TInt bufLength = ByteWidth(height, aDispMode);
1958 aBuf.SetLength(bufLength);
1959 WhiteFill(ptr, bufLength, aDispMode);
1968 TBool oddx=(aDitherOffset.iX&1);
1969 TBool oddy=(aDitherOffset.iY&1);
1970 height=Min(height,(TInt)((aBuf.MaxLength())<<3));
1971 aBuf.SetLength((height+7)>>3);
1973 for(TInt count=0;count<height;count++)
1981 if (HashTo1bpp(GetGrayPixelEx(aX,slptr),oddx,oddy))
1985 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
1991 height=Min(height,(TInt)((aBuf.MaxLength())<<2));
1992 aBuf.SetLength((height+3)>>2);
1995 if (iHeader.iBitsPerPixel==4 && aDither)
1997 const TInt hasharray[4]={0,3,2,1};
1998 TInt index=(aDitherOffset.iX&1)+((aDitherOffset.iY&1)<<1);
1999 for(TInt count=0;count<height;count++,shift+=2)
2007 col = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
2008 TInt value = col / 5;
2011 if (hasharray[index]<TInt(col))
2016 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2021 for(TInt count=0;count<height;count++,shift+=2)
2029 col = TUint8(GetGrayPixelEx(aX,slptr) >> 6);
2032 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2039 height = Min(height,aBuf.MaxLength()<<1);
2040 aBuf.SetLength((height+1)>>1);
2041 TUint8* ptrLimit = ptr + aBuf.Length() - 1;
2042 while (ptr < ptrLimit)
2044 *ptr = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
2045 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2046 *ptr++ |= GetGrayPixelEx(aX,slptr) & 0xf0;
2047 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2050 // If height is odd, upper 4 bits are zeroed.
2051 *ptr = TUint8(GetGrayPixelEx(aX,slptr) >> 4);
2054 // Only fill upper 4 bits of last byte if height is even.
2055 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2056 *ptr++ = GetGrayPixelEx(aX,slptr) & 0xf0;
2062 height=Min(height,aBuf.MaxLength()<<1);
2063 aBuf.SetLength((height+1)>>1);
2064 TUint8* ptrLimit = ptr + aBuf.Length() - 1;
2066 while (ptr < ptrLimit)
2068 *ptr = TUint8(GetRgbPixelEx(aX,slptr).Color16());
2069 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2070 *ptr++ |= GetRgbPixelEx(aX,slptr).Color16() << 4;
2071 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2074 // If height is odd, upper 4 bits are zeroed.
2075 *ptr = TUint8(GetRgbPixelEx(aX,slptr).Color16());
2078 // Only fill upper 4 bits of last byte if height is even.
2079 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2080 *ptr++ = GetRgbPixelEx(aX,slptr).Color16() << 4;
2086 height = Min(height,aBuf.MaxLength());
2087 aBuf.SetLength(height);
2088 TUint8* ptrLimit = ptr + height;
2089 while (ptr < ptrLimit)
2091 *ptr++ = GetGrayPixelEx(aX,slptr);
2092 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2098 height = Min(height,aBuf.MaxLength());
2099 aBuf.SetLength(height);
2100 TUint8* ptrLimit = ptr + height;
2102 while (ptr < ptrLimit)
2104 *ptr++ = TUint8(GetRgbPixelEx(aX,slptr).Color256());
2105 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2111 height = Min(height,aBuf.MaxLength() >> 1);
2112 aBuf.SetLength(height << 1);
2113 TUint16* dwordPtr = (TUint16*)ptr;
2114 TUint16* ptrLimit = dwordPtr + height;
2116 while (dwordPtr < ptrLimit)
2118 *dwordPtr++ = TUint16(GetRgbPixelEx(aX,slptr)._Color4K());
2119 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2125 height = Min(height,aBuf.MaxLength() >> 1);
2126 aBuf.SetLength(height << 1);
2127 TUint16* dwordPtr = (TUint16*)ptr;
2128 TUint16* ptrLimit = dwordPtr + height;
2130 while (dwordPtr < ptrLimit)
2132 *dwordPtr++ = TUint16(GetRgbPixelEx(aX,slptr)._Color64K());
2133 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2139 height = Min(height,aBuf.MaxLength() / 3);
2140 aBuf.SetLength(height * 3);
2141 const TUint8* ptrLimit = ptr + (height * 3);
2143 while (ptr < ptrLimit)
2145 const TInt color16M = GetRgbPixelEx(aX,slptr)._Color16M();
2146 *ptr++ = TUint8(color16M);
2147 *ptr++ = TUint8(color16M >> 8);
2148 *ptr++ = TUint8(color16M >> 16);
2149 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2158 height = Min(height,aBuf.MaxLength() >> 2);
2159 aBuf.SetLength(height << 2);
2160 TUint32* pixelPtr = (TUint32*)ptr;
2161 TUint32* pixelPtrLimit = pixelPtr + height;
2163 if (aDispMode == EColor16MAP && iSettings.CurrentDisplayMode() == EColor16MA)
2164 while (pixelPtr < pixelPtrLimit)
2166 *pixelPtr++ = NonPMA2PMAPixel(*(slptr + aX));
2167 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2169 else if (aDispMode == EColor16MAP && iSettings.CurrentDisplayMode() == EColor16MAP)
2170 while (pixelPtr < pixelPtrLimit)
2172 *pixelPtr++ = *(slptr + aX);
2173 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2175 else if (aDispMode == EColor16MU)
2176 while (pixelPtr < pixelPtrLimit)
2178 *pixelPtr++ = GetRgbPixelEx(aX, slptr).Internal() | 0xFF000000;
2179 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
2182 while (pixelPtr < pixelPtrLimit)
2184 *pixelPtr++ = GetRgbPixelEx(aX, slptr).Internal();
2185 slptr = aRasterizer ? const_cast<TUint32*>(aRasterizer->ScanLine(Extra()->iSerialNumber, TPoint(aX,++y), 1)) : slptr + wordwidth;
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
2196 TLineScanningPosition pos(aBase);
2197 StretchScanLine(aBuf,aPixel,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,pos);
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
2204 TInt x=aPixel.iX,y=aPixel.iY;
2205 if (x>=iHeader.iSizeInPixels.iWidth || x<-iHeader.iSizeInPixels.iWidth)
2206 x%=iHeader.iSizeInPixels.iWidth;
2207 if (y>=iHeader.iSizeInPixels.iHeight || y<-iHeader.iSizeInPixels.iHeight)
2208 y%=iHeader.iSizeInPixels.iHeight;
2209 if (x<0) x+=iHeader.iSizeInPixels.iWidth;
2210 if (y<0) y+=iHeader.iSizeInPixels.iHeight;
2211 if (aStretchLength<aOrgLen)
2212 DoCompressScanLine(aBuf,x,y,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,aLineScanningPosition);
2214 DoStretchScanLine(aBuf,x,y,aClipStrchX,aClipStrchLen,aStretchLength,aOrgX,aOrgLen,aDitherOffset,aDispMode,aBase,aLineScanningPosition);
2217 EXPORT_C TUint32* CBitwiseBitmap::ScanLineAddress(TUint32* aBase,TUint aY) const
2219 if (aY == 0 || iDataOffset == 0)
2222 if (aY >= TUint(iHeader.iSizeInPixels.iHeight))
2223 aY %= iHeader.iSizeInPixels.iHeight;
2225 return aBase + (aY * (DataStride() >> 2));
2228 TUint32* CBitwiseBitmap::DataAddress() const
2230 if (iDataOffset==0) return(NULL);
2232 if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid) // RHardwareBitmap
2234 RHardwareBitmap hwb(iDataOffset); // iDataOffset = handle for hardware bitmap
2235 TAcceleratedBitmapInfo info;
2236 const TInt ret = hwb.GetInfo(info);
2237 return ret!=KErrNone ? NULL : (reinterpret_cast<TUint32*>(info.iAddress));
2241 return(reinterpret_cast<TUint32*>((TUint8*)this+iDataOffset));
2242 return(reinterpret_cast<TUint32*>(iPile->ChunkBase()+iDataOffset));
2245 EXPORT_C TInt CBitwiseBitmap::DataStride() const
2250 TUint32 CBitwiseBitmap::HashTo2bpp(TUint32 aGray256,TInt aDitherIndex) const
2252 static const TUint hasharray[4]={0,3,2,1};
2253 TInt gray16 = aGray256 >> 4;
2254 TInt gray4 = gray16 + 1;
2255 gray4 += gray4 << 1;
2260 if (hasharray[aDitherIndex] < TUint(gray16))
2265 TUint32 CBitwiseBitmap::HashTo1bpp(TUint32 aGray256,TBool aOddX,TBool aOddY) const
2267 TUint32 aGray4 = aGray256 >> 6;
2281 if ((aOddX && aOddY) || (!aOddX && !aOddY))
2284 //coverity [fallthrough]
2291 Tests whether or not the bitmap is monochrome.
2292 Monochrome bitmaps have a display-mode of 1 bit-per-pixel.
2293 Note: The method works for uncompressed bitmaps only.
2294 @param aBase Bitmap's data base address
2295 @return True if the bitmap is monochrome; false otherwise.
2297 EXPORT_C TBool CBitwiseBitmap::IsMonochrome(TUint32* aBase) const
2301 __ASSERT_DEBUG(EFalse, ::Panic(EFbsBitmapInvalidCompression));
2302 return EFalse; // Not currently supported for compressed bitmaps
2309 TInt bitwidth=iHeader.iBitsPerPixel*iHeader.iSizeInPixels.iWidth;
2310 if(iHeader.iBitsPerPixel == 12)
2311 {//EColor4K mode - 1 pixel occupies 16 bits, most significant 4 bits are not used.
2312 bitwidth=16*iHeader.iSizeInPixels.iWidth;
2314 TInt wordwidth=bitwidth>>5;
2315 TInt endshift=32-(bitwidth&0x1f);
2317 if (endshift<32) endmask=0xffffffff>>endshift;
2318 TUint32* bitptr=aBase;
2319 //In a loop from first to last scanline:
2320 //Check each pixel - is it monochrome or not (pixel color must be BLACK or WHITE).
2321 //Get next scanline.
2322 TUint32* endbitptr=bitptr+wordwidth;
2323 for(TInt row=0;row<iHeader.iSizeInPixels.iHeight;row++)
2325 if(iHeader.iBitsPerPixel == 24)
2326 {//1 word contains 1 pixel and 8 bits from the next pixel.
2327 for(TInt x=0;x<iHeader.iSizeInPixels.iWidth;x++)
2329 TUint8* scanLine = reinterpret_cast <TUint8*> (bitptr) + x * 3;
2330 TUint color16M = *scanLine++;
2331 color16M |= (*scanLine++) << 8;
2332 color16M |= (*scanLine++) << 16;
2333 if (IsWordMonochrome(color16M)==EFalse)
2339 TUint32* tmpbitptr=bitptr;
2340 while(tmpbitptr<endbitptr)
2341 if (IsWordMonochrome(*tmpbitptr++)==EFalse)
2344 if (IsWordMonochrome(*endbitptr&endmask)==EFalse)
2348 endbitptr+=wordwidth;
2353 TBool CBitwiseBitmap::IsWordMonochrome(TUint32 aWord) const
2355 TDisplayMode displayMode = iSettings.CurrentDisplayMode();
2362 TUint32 lowerbits=aWord&0x55555555;
2363 TUint32 upperbits=(aWord>>1)&0x55555555;
2364 if (lowerbits^upperbits)
2371 if (aWord==0xffffffff || aWord==0)
2373 for(TInt count=0;count<8;count++)
2375 TUint32 nibble=aWord&0xf;
2376 if ((nibble>0) && (nibble<0xf))
2385 TUint8* bytePtr = (TUint8*)&aWord;
2386 TUint8* bytePtrLimit = bytePtr + 4;
2387 while (bytePtr < bytePtrLimit)
2389 if (*bytePtr && (*bytePtr != 0xff))
2397 aWord &= 0x0fff0fff;
2398 TUint16 color4K = (TUint16)aWord;
2399 if (color4K && (color4K != 0xfff))
2401 color4K = (TUint16)(aWord >> 16);
2402 if (color4K && (color4K != 0xfff))
2408 TUint16 color64K = (TUint16)aWord;
2409 if (color64K && (color64K != 0xffff))
2411 color64K = (TUint16)(aWord >> 16);
2412 if (color64K && (color64K != 0xffff))
2422 if (aWord && (aWord != 0x00ffffff))
2431 EXPORT_C TBool CBitwiseBitmap::IsLargeBitmap() const
2433 if(iUid.iUid==KCBitwiseBitmapHardwareUid.iUid)
2434 return EFalse; // RHardwareBitmap
2436 if (iHeap==NULL) return(EFalse); // rom bitmap
2438 // Consider all RAM bitmaps large, so that legacy applications always
2439 // call LockHeap()/UnlockHeap() around DataAddress(), which allows
2440 // better handling of hardware acceleration caches, if present.
2441 // Note that, since the large bitmap threshold has always been in the
2442 // documentation, it is not guaranteed that legacy applications call
2443 // this function to determine whether a bitmap is large or not.
2447 EXPORT_C TInt CBitwiseBitmap::HardwareBitmapHandle() const
2449 if(iUid.iUid!=KCBitwiseBitmapHardwareUid.iUid)
2451 return iDataOffset; // Really the handle
2455 Set a flag to indicate that this bitmap has to be compressed in the FBServer background thread
2456 @return KErrNone if possible to compress, KErrAlreadyExists if already compressed
2458 EXPORT_C TInt CBitwiseBitmap::CheckBackgroundCompressData()
2460 switch (iHeader.iBitsPerPixel)
2472 return KErrNotSupported;
2474 // Return if the bitmap is already compressed.
2475 if (iHeader.iCompression != ENoBitmapCompression)
2476 return KErrAlreadyExists;
2478 // See if it's possible to allocate memory.
2479 if (iHeap == NULL || iPile == NULL)
2480 return KErrNoMemory;
2488 Compress a bitmap if possible.
2489 If the bitmap is already compressed, or if compression yields no decrease in size, do nothing,
2490 but return success (KErrNone).
2491 @return KErrNone if successful, otherwise a system wide error code.
2493 EXPORT_C TInt CBitwiseBitmap::CompressData()
2495 switch (iHeader.iBitsPerPixel)
2509 // Return if the bitmap is already compressed.
2510 if (iHeader.iCompression != ENoBitmapCompression)
2513 // Find out if compression is possible and return if not.
2514 TUint8* data = (TUint8*)DataAddress();
2515 TInt data_bytes = iHeader.iBitmapSize - iHeader.iStructSize;
2517 //Update the padding bitmap data to speedup the RLE Compression
2518 UpdatePaddingData((TUint32*)data);
2520 TInt compressed_data_bytes = (SizeOfDataCompressed((TUint8*)data,data_bytes) + 3) / 4 * 4;
2522 if (!data || !data_bytes)
2525 // if (compressed_data_bytes >= data_bytes)
2526 // It now attempts to check whether compression is worth while. (speed vs space saving)
2527 __ASSERT_DEBUG(KCompressionThreshold >=0 && KCompressionThreshold <= 256, ::Panic(EFbsInvalidCompressionThreshold));
2528 if (compressed_data_bytes >= (data_bytes * KCompressionThreshold) >> 8)
2531 // See if it's possible to allocate memory.
2532 if (iHeap == NULL || iPile == NULL)
2533 return KErrNoMemory;
2535 // Create a buffer to receive the compressed data.
2536 TUint8* compressed_data = NULL;
2537 TInt allocSize = compressed_data_bytes;
2538 TBool bookMark = EFalse;
2539 if (allocSize > KCompressionBookMarkThreshold)
2541 allocSize += sizeof(TCompressionBookMark) + 4;
2544 compressed_data = iPile->Alloc(allocSize);
2545 if (!compressed_data)
2546 return KErrNoMemory;
2549 TCompressionBookMark emptyBookmark;
2550 *((TCompressionBookMark*)(compressed_data + compressed_data_bytes + 4)) = emptyBookmark;
2552 iDataOffset = compressed_data - iPile->ChunkBase();
2553 iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + compressed_data_bytes;
2554 iHeader.iCompression = CompressionType(iHeader.iBitsPerPixel, iHeader.iColor);
2556 // Compress the data into a stream over the new buffer.
2557 TPtr8 output_ptr(compressed_data,compressed_data_bytes);
2558 RDesWriteStream output_stream(output_ptr);
2559 // This function cannot leave - but trap it anyway till I am fully satisfied about that.
2560 TRAP_IGNORE(DoExternalizeDataCompressedL(output_stream,data,data_bytes));
2561 output_stream.Close();
2563 iIsCompressedInRAM = ETrue;
2564 // Free the old data.
2571 Compress a bitmap if possible.
2572 If the bitmap is already compressed, or if compression yields no decrease in size, do nothing,
2573 but return success (KErrNone).
2575 @param aScheme The type of bitmap file compression.
2576 @return KErrNone if successful, otherwise a system wide error code.
2578 EXPORT_C TInt CBitwiseBitmap::CompressData(TBitmapfileCompressionScheme aScheme)
2581 if (aScheme==ERLECompression)
2583 else if (aScheme==EPaletteCompression)
2584 err=PaletteCompress();
2585 else if (aScheme==EPaletteCompressionWithRLEFallback)
2587 err=PaletteCompress();
2588 if (err==KErrNotSupported)
2595 EXPORT_C TBool CBitwiseBitmap::IsCompressedInRAM() const
2597 return iIsCompressedInRAM;
2601 Check for a bitmap if it is compressed in some manner.
2602 @return ETrue if successful Or EFalse if unsuccessful
2605 EXPORT_C TBool CBitwiseBitmap::IsCompressed() const
2607 return ( iHeader.iCompression != ENoBitmapCompression );
2610 EXPORT_C void CBitwiseBitmap::SetCompressionBookmark(TLineScanningPosition& aLineScanningPosition, TUint32* aBase, const CFbsBitmap* /*aFbsBitmap*/)
2612 if (iPile == NULL) return; //Rom bitmap
2613 if (!iIsCompressedInRAM || (iHeader.iCompression == EGenericPaletteCompression))
2618 TInt compressed_data_bytes=iHeader.iBitmapSize-sizeof(SEpocBitmapHeader);
2619 if (compressed_data_bytes>KCompressionBookMarkThreshold)
2621 TUint8* compressed_data=(TUint8*) aBase;
2622 TInt alignedSize=(compressed_data_bytes+3)/4*4;
2623 compressed_data+=alignedSize+4;
2624 TCompressionBookMark* bookMark=(TCompressionBookMark*) (compressed_data);
2625 if (!bookMark->IsCheckSumOk())
2627 bookMark->iCursorPos=aLineScanningPosition.iCursorPos;
2628 bookMark->iSrcDataOffset=aLineScanningPosition.iSrcDataPtr-((TUint8*)aBase);
2629 bookMark->CalculateCheckSum();
2633 Optimises the bitmap data for Run Length Encoding by changing unused
2635 This function calculates number of padding pixels per scanline and
2636 replaces their color with the color of the scanline's final pixel.
2638 void CBitwiseBitmap::UpdatePaddingData(TUint32* aData)
2640 TInt stride=DataStride();
2641 //Do the process only for 8bpp and 16bpp.
2642 switch (iHeader.iBitsPerPixel)
2646 const TInt nPadding = stride - iHeader.iSizeInPixels.iWidth;
2647 if(nPadding!=1 && nPadding!=2 && nPadding!=3)
2649 TUint8* srcePtr = reinterpret_cast<TUint8*>(aData);
2650 //Find the last byte value in each scanline and assign in padding bytes
2651 TUint8* lastPixelPtr = srcePtr + iHeader.iSizeInPixels.iWidth - 1;
2652 for(TInt row=0; row<iHeader.iSizeInPixels.iHeight; row++)
2654 TUint8 pixel = *lastPixelPtr;
2655 TUint8* padPtr = lastPixelPtr + 1;
2658 case 3: *padPtr++ = pixel;
2659 case 2: *padPtr++ = pixel;
2660 case 1: *padPtr++ = pixel;
2662 lastPixelPtr += stride;
2668 TUint16* srcePtr = reinterpret_cast<TUint16*>(aData);
2670 const TInt nPadding = stride - iHeader.iSizeInPixels.iWidth;
2673 //Find the last byte value in each scanline and assign in padding bytes
2674 TUint16* lastPixelPtr = srcePtr + iHeader.iSizeInPixels.iWidth - 1;
2675 for(TInt row=0; row<iHeader.iSizeInPixels.iHeight; row++)
2677 TUint16 pixel = *lastPixelPtr;
2678 TUint16* padPtr = lastPixelPtr + 1;
2680 lastPixelPtr += stride;
2689 void CBitwiseBitmap::WhiteFill(TUint8* aData,TInt aDataSize,TDisplayMode aDispMode)
2693 if (aDispMode != EColor4K)
2694 Mem::Fill(aData,aDataSize,0xff);
2697 TUint16* pixelPtr = (TUint16*)aData;
2698 TUint16* pixelPtrLimit = pixelPtr + (aDataSize / 2);
2699 while (pixelPtr < pixelPtrLimit)
2700 *pixelPtr++ = 0x0fff;
2705 TInt CBitwiseBitmap::ByteWidth(TInt aPixelWidth,TDisplayMode aDispMode)
2712 wordWidth = (aPixelWidth + 31) / 32;
2715 wordWidth = (aPixelWidth + 15) / 16;
2719 wordWidth = (aPixelWidth + 7) / 8;
2723 wordWidth = (aPixelWidth + 3) / 4;
2727 wordWidth = (aPixelWidth + 1) / 2;
2730 wordWidth = (((aPixelWidth * 3) + 11) / 12) * 3;
2736 wordWidth = aPixelWidth;
2739 ::Panic(EFbsBitmapInvalidMode);
2742 return wordWidth * 4;
2745 TInt CBitwiseBitmap::Bpp(TDisplayMode aDispMode)
2770 ::Panic(EFbsBitmapInvalidMode);
2776 TInt CBitwiseBitmap::CompressedFormatInfo(TDisplayMode aDispMode, TInt& aBytesPerPack, TInt& aBytesPerCompressed)
2787 aBytesPerCompressed = 1;
2792 aBytesPerCompressed = 2;
2796 aBytesPerCompressed = 3;
2800 aBytesPerCompressed = 3; //when compressed, 16MU is stored as 16M
2805 aBytesPerCompressed = 4;
2808 __ASSERT_DEBUG(0, ::Panic(EFbsBitmapInvalidMode));
2809 return KErrNotSupported;
2814 TInt CBitwiseBitmap::IsColor(TDisplayMode aDispMode)
2822 return SEpocBitmapHeader::ENoColor;
2829 return SEpocBitmapHeader::EColor;
2831 return SEpocBitmapHeader::EColorAlpha;
2833 return SEpocBitmapHeader::EColorAlphaPM;
2835 ::Panic(EFbsBitmapInvalidMode);
2838 return SEpocBitmapHeader::EColorUndefined;
2841 TDisplayMode CBitwiseBitmap::DisplayMode(TInt aBpp, TInt aColor)
2858 if(aColor == SEpocBitmapHeader::EColor)
2860 else if(aColor == SEpocBitmapHeader::EColorAlphaPM)
2862 else if(aColor == SEpocBitmapHeader::EColorAlpha)
2888 TBitmapfileCompression CBitwiseBitmap::CompressionType(TInt aBpp, TInt aColor)
2896 return EByteRLECompression;
2898 return ETwelveBitRLECompression;
2900 return ESixteenBitRLECompression;
2902 return ETwentyFourBitRLECompression;
2904 __ASSERT_DEBUG((aColor==SEpocBitmapHeader::EColor) ||
2905 (aColor==SEpocBitmapHeader::EColorAlpha) ||
2906 aColor==SEpocBitmapHeader::EColorAlphaPM,
2907 ::Panic(EFbsBitmapInvalidCompression));
2908 if(aColor == SEpocBitmapHeader::EColor)
2910 return EThirtyTwoUBitRLECompression;
2914 return EThirtyTwoABitRLECompression;
2917 return ENoBitmapCompression;
2923 @return The display mode used to create the bitmap.
2925 TDisplayMode CBitwiseBitmap::InitialDisplayMode() const
2927 return iSettings.InitialDisplayMode();
2931 The method changes current display mode of the bitmap.
2932 Requested display mode can't be greater (bpp value) than the initial display mode.
2933 CBitwiseBitmap instances are shared between the client and server side and
2934 SetDisplayMode() can be called only from the client side, because its functionality depends
2935 on the RFbsSession instance.
2936 The method can't leave because of out of memory condition or something else - no
2937 additional memory is allocated or "L" methods called.
2938 The bitmap content is preserved when converting it to the requested display mode,
2939 but there may be some loss of a quality.
2941 @param aDisplayMode Requested display mode.
2942 @param aDataAddress Bitmap data address.
2943 @return KErrArgument If the requested mode is invalid, or greater (bpp value) than the
2944 initial display mode.
2945 @return KErrNotSupported If the bitmap is compressed, or it is a ROM bitmap,
2946 an extended bitmap or a hardware bitmap.
2947 @return KErrNone If the method call is successfull.
2949 TInt CBitwiseBitmap::SetDisplayMode(TDisplayMode aDisplayMode, TUint32* aDataAddress)
2951 TDisplayMode curDisplayMode = iSettings.CurrentDisplayMode();
2952 //If requested mode is the same as current mode - do nothing.
2953 if(curDisplayMode == aDisplayMode)
2957 //Argument and bitmap state check.
2958 TInt err = DisplayModeArgCheck(aDisplayMode, aDataAddress);
2963 //data pointers and scan line width calculation.
2964 TInt scanLineWidthNew = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iWidth, aDisplayMode);
2965 TInt scanLineWidthInitial = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iWidth, iSettings.InitialDisplayMode());
2966 TInt bmpSizeInitial = scanLineWidthInitial * iHeader.iSizeInPixels.iHeight;
2967 TUint8* baseAddr = reinterpret_cast <TUint8*> (aDataAddress);
2968 TUint8* dataAddrNew = baseAddr;
2971 TInt yEnd = iHeader.iSizeInPixels.iHeight;
2972 //If requested display mode has more bits per pixel than current display mode - we have
2973 //to start copying operation from the end of the bitmap, otherwise we will overwrite the
2975 if(aDisplayMode > curDisplayMode)
2977 dataAddrNew += bmpSizeInitial - scanLineWidthNew;
2978 scanLineWidthNew = -scanLineWidthNew;
2983 //Change the display mode
2984 ChangeDisplayMode(aDisplayMode, scanLineWidthNew, dataAddrNew, aDataAddress, yStart, yInc, yEnd);
2985 //Move the data to the aDataAddress.
2986 if(aDisplayMode > curDisplayMode)
2988 TInt bmpSizeNew = -scanLineWidthNew * iHeader.iSizeInPixels.iHeight;
2989 Mem::Move(baseAddr, baseAddr + bmpSizeInitial - bmpSizeNew, bmpSizeNew);
2991 //Update the bitmap properties
2992 UpdateBitmapProperties(aDisplayMode);
2997 The method is caled from CBitwiseBitmap::SetDisplayMode() and
2998 checks the aDisplayMode argument and bitmap internal state.
2999 Requested display mode can't be greater (bpp value) than the initial display mode.
3000 Note: The method must be called only from CBitwiseBitmap::SetDisplayMode method.
3002 @param aDisplayMode Requested display mode.
3003 @param aDataAddress Bitmap data address.
3004 @return KErrArgument If the requested mode is invalid, or greater (bpp value)
3005 than the initial mode.
3006 @return KErrNotSupported If the bitmap is compressed, or it is a ROM bitmap,
3007 an extended bitmap or a hardware bitmap.
3008 @return KErrNone If the method call is successfull.
3009 @see CBitwiseBitmap::SetDisplayMode.
3011 TInt CBitwiseBitmap::DisplayModeArgCheck(TDisplayMode aDisplayMode, TUint32* aDataAddress) const
3013 if(!aDataAddress || iHeader.iSizeInPixels.iWidth == 0 || iHeader.iSizeInPixels.iHeight == 0)
3017 TBool romAddr = EFalse;
3018 User::IsRomAddress(romAddr, aDataAddress);
3019 if(romAddr || //ROM bitmap
3020 (iUid.iUid != KCBitwiseBitmapUid.iUid) || //RHardwareBitmap or extended bitmap
3021 IsCompressed() //Compressed
3024 return KErrNotSupported;
3026 if(aDisplayMode == ENone || aDisplayMode == ERgb)
3028 return KErrArgument;
3030 if (iSettings.InitialDisplayMode()==EColor16 && aDisplayMode==EGray256)
3032 return KErrArgument;
3034 // The order of the display mode in the TDisplayMode
3035 // ENone,EGray2,EGray4,EGray16,EGray256,EColor16,EColor256,EColor64K,EColor16M,ERgb,EColor4K,EColor16MU
3037 //special case where initial mode is EColor4K & to be set to EColor64K & EColor16M which has lower enum
3038 if (iSettings.InitialDisplayMode()==EColor4K )
3040 if (aDisplayMode==EColor64K || aDisplayMode==EColor16M)
3041 return KErrArgument;
3044 if(aDisplayMode == EColor16MAP)
3046 TDisplayMode mode = iSettings.InitialDisplayMode();
3047 if((mode == EColor16MA)||(mode == EColor16MU)||(mode == EColor16MAP))
3052 return KErrArgument;
3055 if(iSettings.InitialDisplayMode() == EColor16MAP)
3059 if(aDisplayMode > iSettings.InitialDisplayMode())
3061 if (iSettings.InitialDisplayMode()>=EColor64K && aDisplayMode == EColor4K)
3065 if (iSettings.InitialDisplayMode()==EColor16MU &&
3066 (Bpp(aDisplayMode) == 32))
3070 return KErrArgument;
3077 The method changes current display mode of the bitmap converting bitmap scan lines
3078 color and writting the resulting scan line to the same memory occupied by the bitmap.
3079 No additional memory is allocated.
3080 Note: The method must be called only from CBitwiseBitmap::SetDisplayMode method.
3082 @param aNewDisplayMode Requested display mode.
3083 @param aScanLineWidthNew Scan line width - with the new display mode. It could be negative
3084 if the new display mode is with less bits per pixel than the existing display mode.
3085 @param aDataAddrNew New bitmap data - Points to the place where the copying has to start to.
3086 @param aDataAddress Bitmap data address.
3087 @param aYStart First scan line number.
3088 @param aYInc Scan line increment value.
3089 @param aYEnd Last scan line number.
3090 @see CBitwiseBitmap::SetDisplayMode.
3092 void CBitwiseBitmap::ChangeDisplayMode( TDisplayMode aNewDisplayMode,
3093 TInt aScanLineWidthNew,
3094 TUint8* aDataAddrNew,
3095 TUint32* aDataAddress,
3100 const TInt KScanLineBufSizeInPixels = 256;//temporary scan line buffer size - in pixels
3101 const TInt KRgbBytes = 4;
3102 const TInt KScanLineBufSizeInBytes = KScanLineBufSizeInPixels * KRgbBytes;
3103 TUint8 scanLineData[KScanLineBufSizeInBytes];
3104 static const TInt KScanLinePixels[] = //The rounded number of pixels - the closest number that
3105 { //could fill scanLineData buffer - depending on current display mode
3106 0, //ENone - INVALID mode
3107 KScanLineBufSizeInBytes * 8, //EGray2
3108 KScanLineBufSizeInBytes * 4, //EGray4
3109 KScanLineBufSizeInBytes * 2, //EGray16
3110 KScanLineBufSizeInBytes * 1, //EGray256
3111 KScanLineBufSizeInBytes * 2, //EColor16
3112 KScanLineBufSizeInBytes * 1, //EColor256
3113 KScanLineBufSizeInPixels * KRgbBytes / 2, //EColor64K
3114 KScanLineBufSizeInPixels, //EColor16M
3115 0, //ERgb - INVALID mode
3116 KScanLineBufSizeInPixels * KRgbBytes / 2, //EColor4K - the same as EColor64K
3117 KScanLineBufSizeInPixels * KRgbBytes / 4, //EColor16MU
3118 KScanLineBufSizeInPixels * KRgbBytes / 4, //EColor16MA
3119 KScanLineBufSizeInPixels * KRgbBytes / 4 //EColor16MAP
3121 __ASSERT_DEBUG(aNewDisplayMode < TInt(sizeof(KScanLinePixels) / sizeof(KScanLinePixels[0])), ::Panic(EFbsBitmapInvalidMode3));
3123 TPtr8 ptr(scanLineData, sizeof(scanLineData), sizeof(scanLineData));
3124 TDes8& scanLineDes = ptr;
3125 TLineScanningPosition lineScanningPosition(aDataAddress);
3126 TPoint startPixel(0, 0);
3127 TPoint ditherOffset(0, 0);
3129 //1. Get a scan line in requested display mode
3130 //2. Copy the scan line to the destination buffer, pointed by dataAddrNew
3131 TUint8* dataAddrNew = aDataAddrNew;
3132 for(TInt i=aYStart;i!=aYEnd;i+=aYInc)
3136 TUint8* scanLineDataAddr = dataAddrNew;
3137 TInt scanLinePixelsLeft = iHeader.iSizeInPixels.iWidth;
3138 while(scanLinePixelsLeft > 0)
3140 TInt pixelsCnt = KScanLinePixels[aNewDisplayMode]; //how many pixels we can get at a time - the maximum
3141 TInt bytesCnt = KScanLineBufSizeInBytes; //how many bytes the pixels are - the maximum
3142 if(pixelsCnt > scanLinePixelsLeft) //in that case the "while" loop will be executed for the last time
3144 pixelsCnt = scanLinePixelsLeft;
3145 bytesCnt = CBitwiseBitmap::ByteWidth(pixelsCnt, aNewDisplayMode);
3147 __ASSERT_DEBUG(pixelsCnt > 0, ::Panic(EFbsBitmapInvalidMode2));//I want to be sure - if someone adds an additional display mode - ChangeDisplayMode() source has been updated too!
3148 GetScanLine(scanLineDes, startPixel, pixelsCnt, EFalse, //Get the scan line data
3149 ditherOffset, aNewDisplayMode, aDataAddress, lineScanningPosition);
3150 Mem::Copy(scanLineDataAddr, scanLineData, bytesCnt);//copy the data to its new address
3151 scanLineDataAddr += bytesCnt;//increment the address
3152 scanLinePixelsLeft -= pixelsCnt;//decrement the count of pixels left
3153 startPixel.iX += pixelsCnt;//increment the X coordinate
3154 }//end of - while(scanLineLengthLeft > 0)
3155 dataAddrNew += aScanLineWidthNew;
3156 }//end of - for(TInt i=aYStart;i!=aYEnd;i+=aYInc)
3160 The method updates CBitwiseBitmap data members regarding to the new display mode.
3161 Note: The method must be called only from CBitwiseBitmap::SetDisplayMode method.
3163 @param aNewDisplayMode The new display mode.
3164 @see CBitwiseBitmap::SetDisplayMode.
3166 void CBitwiseBitmap::UpdateBitmapProperties(TDisplayMode aNewDisplayMode)
3168 iSettings.SetCurrentDisplayMode(aNewDisplayMode);
3169 iByteWidth = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iWidth, aNewDisplayMode);
3170 iHeader.iBitsPerPixel = CBitwiseBitmap::Bpp(aNewDisplayMode);
3171 iHeader.iColor = CBitwiseBitmap::IsColor(aNewDisplayMode);
3175 The method swaps the bitmap width and height.
3176 For example: if the bitmap size is (40, 20), the new bitmap size will be (20, 40).
3177 Bitmap content is not preserved.
3179 @param aDataAddress Bitmap data address.
3180 @return KErrNone The call was successfull.
3181 @return KErrAccessDenied ROM bitmap size can't be swapped.
3182 @return KErrNotSupported Hardware or extended bitmap size can't be swapped.
3184 TInt CBitwiseBitmap::SwapWidthAndHeight(TUint32* aDataAddress)
3186 if (iUid.iUid != KCBitwiseBitmapUid.iUid) // RHardwareBitmap or extended bitmap
3188 return KErrNotSupported;
3191 TBool romAddr = EFalse;
3192 User::IsRomAddress(romAddr, aDataAddress);
3193 if (romAddr) //ROM bitmap
3195 return KErrAccessDenied;
3198 //Check the new bitmap size - it should not exeed the size of the allocated memory
3199 TInt newWidthInBytes = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iHeight, iSettings.CurrentDisplayMode());
3200 TInt64 hugeDataSize = TInt64(iHeader.iSizeInPixels.iWidth) * TInt64(newWidthInBytes);
3201 __ASSERT_ALWAYS(I64HIGH(hugeDataSize) == 0 &&
3202 I64LOW(hugeDataSize) <= TUint(iHeader.iBitmapSize - iHeader.iStructSize),
3203 ::Panic(EFbsBitmapSwappingImpossible));
3205 //Initialize the data members with the new values
3206 iByteWidth = CBitwiseBitmap::ByteWidth(iHeader.iSizeInPixels.iHeight, iSettings.CurrentDisplayMode());
3207 TInt temp = iHeader.iSizeInPixels.iWidth;
3208 iHeader.iSizeInPixels.iWidth = iHeader.iSizeInPixels.iHeight;
3209 iHeader.iSizeInPixels.iHeight = temp;
3210 temp = iHeader.iSizeInTwips.iWidth;
3211 iHeader.iSizeInTwips.iWidth = iHeader.iSizeInTwips.iHeight;
3212 iHeader.iSizeInTwips.iHeight = temp;
3217 Compile time check is performed on the class size - the class size must be
3218 the same as the size of TDisplayMode type. If the class size is not the same
3219 as TDisplayMode type size - BC will be broken.
3220 Note: CBitwiseBitmap::iSettings data member must be aligned on 16 bits boundary
3221 because CBitwiseBitmap instances can be a part of the ROM image.
3223 @param aDisplayMode The display mode.
3225 CBitwiseBitmap::TSettings::TSettings(TDisplayMode aDisplayMode):
3228 //"CBitwiseBitmap::iSettings" data mamber - bit format:
3231 // Flags Initial display mode Current display mode
3233 //CBitwiseBitmap - TSettings member has been put in place of previous iDispMode
3234 //class member. So, TSettings data member has to occupy the same space as
3235 //not existing anymore iDispMode member.
3236 COMPILE_TIME_ASSERT(sizeof(TSettings) == sizeof(TDisplayMode));
3237 //We can't have TDisplayMode enum value greater than 255 because we encode it
3238 //int 8 bits of iData data member.
3239 COMPILE_TIME_ASSERT(EColorLast < 256);
3240 SetDisplayModes(aDisplayMode);
3244 The method initializes both - current display mode and initial display mode parts of iData
3245 with aDisplayMode parameter.
3247 @param aDisplayMode The display mode used for current display mode and initial display mode
3248 parts of iData initialization
3250 void CBitwiseBitmap::TSettings::SetDisplayModes(TDisplayMode aDisplayMode)
3252 iData &= 0xFFFF0000;
3253 iData |= TUint16(aDisplayMode << 8);
3254 iData |= TUint8(aDisplayMode);
3258 The method initializes current display mode part of iData with aDisplayMode parameter.
3260 @param aDisplayMode The display mode used for current display mode part of iData initialization.
3262 void CBitwiseBitmap::TSettings::SetCurrentDisplayMode(TDisplayMode aDisplayMode)
3264 iData &= 0xFFFFFF00;
3265 iData |= TUint8(aDisplayMode);
3269 The method returns current display mode.
3271 Note: Current display mode can never be greater (bpp value) than initial display mode.
3272 @return Current display mode.
3274 TDisplayMode CBitwiseBitmap::TSettings::CurrentDisplayMode() const
3276 return TDisplayMode(iData & 0x000000FF);
3280 The method returns initial display mode.
3282 @return The initial display mode.
3284 TDisplayMode CBitwiseBitmap::TSettings::InitialDisplayMode() const
3286 return TDisplayMode((iData & 0x0000FF00) >> 8);
3290 The method adjusts specified X coordinate if it is negative or outside the bitmap.
3292 @param aX - a reference to x coordinate - the value might be changed after the method call.
3294 void CBitwiseBitmap::AdjustXCoord(TInt& aX) const
3296 if (aX>=iHeader.iSizeInPixels.iWidth || aX<-iHeader.iSizeInPixels.iWidth)
3297 aX%=iHeader.iSizeInPixels.iWidth;
3299 aX+=iHeader.iSizeInPixels.iWidth;
3303 If the bitmap is compressed in RAM, the method will find its compresssion bookmark,
3304 which is located at the end of the bitmap data and will reinitialize aLineScanPos
3307 @param aLineScanPos Line scaning position. It is used by scan line decompression methods.
3308 @param aComprBookMark If the bitmap is compressed in RAM, aComprBookMark will be initialized
3309 to point to its compression bookmark data. The compression bookmark data will be used for
3310 aLineScanPos initialization.
3311 @param aBase It points to the beginning of the bitmap data.
3313 void CBitwiseBitmap::GetLineScanPos(TLineScanningPosition& aLineScanPos,
3314 const TCompressionBookMark*& aComprBookMark,
3315 const TUint8* aBase) const
3317 if (iIsCompressedInRAM && (iHeader.iCompression != EGenericPaletteCompression) && (iHeap != NULL))
3319 TInt compressed_data_bytes = iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
3320 if(compressed_data_bytes > KCompressionBookMarkThreshold)
3324 TInt alignedSize = (compressed_data_bytes + 3) / 4 * 4;
3325 const TUint8* data = aBase + alignedSize + 4;
3326 aComprBookMark = reinterpret_cast <const TCompressionBookMark*> (data);
3327 if (aComprBookMark->IsCheckSumOk())
3329 aLineScanPos.iSrcDataPtr = const_cast <TUint8*> (aBase) + aComprBookMark->iSrcDataOffset;
3330 aLineScanPos.iCursorPos = aComprBookMark->iCursorPos;
3338 If the bitmap is compressed in RAM, the method will update its compresssion bookmark data,
3339 which is located at the end of the bitmap data.
3341 @param aLineScanPos Line scaning position.
3342 @param aComprBookMark If the bitmap is compressed in RAM, aComprBookMark points to its
3343 compression bookmark data.
3344 @param aBase It points to the beginning of the bitmap data.
3346 void CBitwiseBitmap::UpdateBookMark(const TLineScanningPosition& aLineScanPos,
3347 TCompressionBookMark* aComprBookMark,
3348 const TUint8* aBase) const
3352 if (aComprBookMark->IsCheckSumOk())
3354 aComprBookMark->iSrcDataOffset=aLineScanPos.iSrcDataPtr-aBase;
3355 aComprBookMark->iCursorPos=aLineScanPos.iCursorPos;
3356 aComprBookMark->CalculateCheckSum();
3362 The header is exposed by CFbsBitmap so this doesn't break encapsulation.
3363 Specifically added to allow CBitmapObject to see compression information.
3364 @return Address of iHeader.
3366 EXPORT_C SEpocBitmapHeader CBitwiseBitmap::Header() const