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