sl@0
|
1 |
// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
//
|
sl@0
|
15 |
|
sl@0
|
16 |
#include <e32base.h>
|
sl@0
|
17 |
#include <bitmap.h>
|
sl@0
|
18 |
#include "CompressionBookmark.h"
|
sl@0
|
19 |
#include "BitmapCompr.h"
|
sl@0
|
20 |
#include "UTILS.H"
|
sl@0
|
21 |
#include "bitmapconst.h"
|
sl@0
|
22 |
|
sl@0
|
23 |
GLREF_C void Panic(TFbsPanic aPanic);
|
sl@0
|
24 |
|
sl@0
|
25 |
/**
|
sl@0
|
26 |
The method recalculates aLineScanPos which is used for quick search of the
|
sl@0
|
27 |
nearest "length" byte before aStartPos.
|
sl@0
|
28 |
Note: The method should be used only for compressed in RAM bitmaps for which
|
sl@0
|
29 |
iPile != NULL.
|
sl@0
|
30 |
@internalComponent
|
sl@0
|
31 |
@post aLineScanPos might be updated
|
sl@0
|
32 |
*/
|
sl@0
|
33 |
GLDEF_C void AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos,
|
sl@0
|
34 |
const TUint32* aBase,
|
sl@0
|
35 |
TInt aBitmapWidth,
|
sl@0
|
36 |
TInt aStartPos,
|
sl@0
|
37 |
TInt aCompressedDataBytes)
|
sl@0
|
38 |
{
|
sl@0
|
39 |
TInt difference = ::Abs(aStartPos - aLineScanPos.iCursorPos);
|
sl@0
|
40 |
if(difference > aBitmapWidth && aCompressedDataBytes > KCompressionBookMarkThreshold)
|
sl@0
|
41 |
{
|
sl@0
|
42 |
const TCompressionBookMark* bookMarkPtr =
|
sl@0
|
43 |
(const TCompressionBookMark*)((const TUint8*)aBase +
|
sl@0
|
44 |
(aCompressedDataBytes + 3) / 4 * 4 + 4);
|
sl@0
|
45 |
if(bookMarkPtr->iSrcDataOffset && bookMarkPtr->IsCheckSumOk())
|
sl@0
|
46 |
{
|
sl@0
|
47 |
TInt difference2 = ::Abs(aStartPos - bookMarkPtr->iCursorPos);
|
sl@0
|
48 |
if(difference2 < difference)
|
sl@0
|
49 |
{
|
sl@0
|
50 |
aLineScanPos.iCursorPos = bookMarkPtr->iCursorPos;
|
sl@0
|
51 |
aLineScanPos.iSrcDataPtr = ((TUint8*)aBase) + bookMarkPtr->iSrcDataOffset;
|
sl@0
|
52 |
}
|
sl@0
|
53 |
}
|
sl@0
|
54 |
}
|
sl@0
|
55 |
}
|
sl@0
|
56 |
|
sl@0
|
57 |
/**
|
sl@0
|
58 |
The method gets the first 16 bpp pixel value pointed by aSrcPtr and copies it aCount times
|
sl@0
|
59 |
to aDestPtr buffer.
|
sl@0
|
60 |
@internalComponent
|
sl@0
|
61 |
@pre aCount > 0
|
sl@0
|
62 |
@param aSrcPtr It points to the source pixel
|
sl@0
|
63 |
@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
|
sl@0
|
64 |
@param aCount How many times the pixel value should be copied
|
sl@0
|
65 |
@return The updated aDestPtr
|
sl@0
|
66 |
*/
|
sl@0
|
67 |
template <>
|
sl@0
|
68 |
TUint8* TScanLineDecompressor<E2bpp, E2bpp>::CopyPixel(TUint8* aDestPtr,
|
sl@0
|
69 |
const TUint8* aSrcPtr,
|
sl@0
|
70 |
TInt aCount) const
|
sl@0
|
71 |
{
|
sl@0
|
72 |
//We can't access directly the 16 bits data chunk, because it may be located at an odd address and
|
sl@0
|
73 |
//THUMB build will fail with "KERNEL EXEC-3".
|
sl@0
|
74 |
TUint8 lsb = *aSrcPtr;
|
sl@0
|
75 |
TUint8 msb = *(aSrcPtr + 1);
|
sl@0
|
76 |
TUint16 data = TUint16(lsb | (TUint16(msb) << 8));
|
sl@0
|
77 |
TUint32 data32 = TUint32(data | (TUint32(data) << 16));
|
sl@0
|
78 |
if((TUint32(aDestPtr) & 0x2) && aCount)
|
sl@0
|
79 |
{
|
sl@0
|
80 |
*(TUint16*)aDestPtr = data;
|
sl@0
|
81 |
aDestPtr += 2;//+= 2 - the pixel color is coded into 16 bits - 2 bytes
|
sl@0
|
82 |
aCount--;
|
sl@0
|
83 |
}
|
sl@0
|
84 |
while(aCount > 1)
|
sl@0
|
85 |
{
|
sl@0
|
86 |
*(TUint32*)aDestPtr = data32;
|
sl@0
|
87 |
aDestPtr += 4;//+= 4 - the pixel color is coded into 16 bits - 2 x 2 bytes
|
sl@0
|
88 |
aCount -= 2;
|
sl@0
|
89 |
}
|
sl@0
|
90 |
if(aCount)
|
sl@0
|
91 |
{
|
sl@0
|
92 |
*(TUint16*)aDestPtr = data;
|
sl@0
|
93 |
aDestPtr += 2;//+= 2 - the pixel color is coded into 16 bits - 2 bytes
|
sl@0
|
94 |
}
|
sl@0
|
95 |
return aDestPtr;
|
sl@0
|
96 |
}
|
sl@0
|
97 |
|
sl@0
|
98 |
/**
|
sl@0
|
99 |
The method gets the first 24 bpp pixel value pointed by aSrcPtr and copies it aCount times
|
sl@0
|
100 |
to aDestPtr buffer.
|
sl@0
|
101 |
@internalComponent
|
sl@0
|
102 |
@pre aCount > 0
|
sl@0
|
103 |
@param aSrcPtr It points to the source pixel
|
sl@0
|
104 |
@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
|
sl@0
|
105 |
@param aCount How many times the pixel value should be copied
|
sl@0
|
106 |
@return The updated aDestPtr
|
sl@0
|
107 |
*/
|
sl@0
|
108 |
template <>
|
sl@0
|
109 |
TUint8* TScanLineDecompressor<E3bpp, E3bpp>::CopyPixel(TUint8* aDestPtr,
|
sl@0
|
110 |
const TUint8* aSrcPtr,
|
sl@0
|
111 |
TInt aCount) const
|
sl@0
|
112 |
{
|
sl@0
|
113 |
const TUint8 b1 = *aSrcPtr;
|
sl@0
|
114 |
const TUint8 b2 = *(aSrcPtr + 1);
|
sl@0
|
115 |
const TUint8 b3 = *(aSrcPtr + 2);
|
sl@0
|
116 |
while(aCount--)
|
sl@0
|
117 |
{
|
sl@0
|
118 |
*aDestPtr++ = b1;
|
sl@0
|
119 |
*aDestPtr++ = b2;
|
sl@0
|
120 |
*aDestPtr++ = b3;
|
sl@0
|
121 |
}
|
sl@0
|
122 |
return aDestPtr;
|
sl@0
|
123 |
}
|
sl@0
|
124 |
|
sl@0
|
125 |
/**
|
sl@0
|
126 |
The method gets the first 32 bpp pixel value pointed by aSrcPtr and copies it aCount times
|
sl@0
|
127 |
to aDestPtr buffer.
|
sl@0
|
128 |
@internalComponent
|
sl@0
|
129 |
@pre aCount > 0
|
sl@0
|
130 |
@param aSrcPtr It points to the source pixel
|
sl@0
|
131 |
@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
|
sl@0
|
132 |
@param aCount How many times the pixel value should be copied
|
sl@0
|
133 |
@return The updated aDestPtr
|
sl@0
|
134 |
*/
|
sl@0
|
135 |
template <>
|
sl@0
|
136 |
TUint8* TScanLineDecompressor<E4bpp, E4bpp>::CopyPixel(TUint8* aDestPtr,
|
sl@0
|
137 |
const TUint8* aSrcPtr,
|
sl@0
|
138 |
TInt aCount) const
|
sl@0
|
139 |
{
|
sl@0
|
140 |
__ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestPtr) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
|
sl@0
|
141 |
|
sl@0
|
142 |
const TUint8 b1 = *aSrcPtr;
|
sl@0
|
143 |
const TUint8 b2 = *(aSrcPtr + 1);
|
sl@0
|
144 |
const TUint8 b3 = *(aSrcPtr + 2);
|
sl@0
|
145 |
const TUint8 b4 = *(aSrcPtr + 3);
|
sl@0
|
146 |
|
sl@0
|
147 |
if((reinterpret_cast<TUint32>(aDestPtr) & 0x3)== 0) // the start address is word aligned
|
sl@0
|
148 |
{
|
sl@0
|
149 |
const TUint32 pixel = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
|
sl@0
|
150 |
TUint32* destPtr32 = reinterpret_cast <TUint32*>(aDestPtr);
|
sl@0
|
151 |
TInt blocksOf16 = ((aCount + 0x0f) >> 4); // number of blocks of upto 16 words to write
|
sl@0
|
152 |
// the first iteration writes 1 to 15 words
|
sl@0
|
153 |
switch (aCount & 0x0f)
|
sl@0
|
154 |
{ // note that case statements intentionally cascade
|
sl@0
|
155 |
case 0:
|
sl@0
|
156 |
do { // second and subsequent iterations always write 16 words
|
sl@0
|
157 |
*destPtr32++ = pixel;
|
sl@0
|
158 |
case 15:
|
sl@0
|
159 |
*destPtr32++ = pixel;
|
sl@0
|
160 |
case 14:
|
sl@0
|
161 |
*destPtr32++ = pixel;
|
sl@0
|
162 |
case 13:
|
sl@0
|
163 |
*destPtr32++ = pixel;
|
sl@0
|
164 |
case 12:
|
sl@0
|
165 |
*destPtr32++ = pixel;
|
sl@0
|
166 |
case 11:
|
sl@0
|
167 |
*destPtr32++ = pixel;
|
sl@0
|
168 |
case 10:
|
sl@0
|
169 |
*destPtr32++ = pixel;
|
sl@0
|
170 |
case 9:
|
sl@0
|
171 |
*destPtr32++ = pixel;
|
sl@0
|
172 |
case 8:
|
sl@0
|
173 |
*destPtr32++ = pixel;
|
sl@0
|
174 |
case 7:
|
sl@0
|
175 |
*destPtr32++ = pixel;
|
sl@0
|
176 |
case 6:
|
sl@0
|
177 |
*destPtr32++ = pixel;
|
sl@0
|
178 |
case 5:
|
sl@0
|
179 |
*destPtr32++ = pixel;
|
sl@0
|
180 |
case 4:
|
sl@0
|
181 |
*destPtr32++ = pixel;
|
sl@0
|
182 |
case 3:
|
sl@0
|
183 |
*destPtr32++ = pixel;
|
sl@0
|
184 |
case 2:
|
sl@0
|
185 |
*destPtr32++ = pixel;
|
sl@0
|
186 |
case 1:
|
sl@0
|
187 |
*destPtr32++ = pixel;
|
sl@0
|
188 |
} while(--blocksOf16 > 0);
|
sl@0
|
189 |
}
|
sl@0
|
190 |
|
sl@0
|
191 |
return reinterpret_cast <TUint8*>(destPtr32);
|
sl@0
|
192 |
}
|
sl@0
|
193 |
|
sl@0
|
194 |
while(aCount--)
|
sl@0
|
195 |
{
|
sl@0
|
196 |
*aDestPtr++ = b1;
|
sl@0
|
197 |
*aDestPtr++ = b2;
|
sl@0
|
198 |
*aDestPtr++ = b3;
|
sl@0
|
199 |
*aDestPtr++ = b4;
|
sl@0
|
200 |
}
|
sl@0
|
201 |
return aDestPtr;
|
sl@0
|
202 |
}
|
sl@0
|
203 |
|
sl@0
|
204 |
/**
|
sl@0
|
205 |
The method gets the first 24 bpp pixel value pointed by aSrcPtr and copies it aCount times
|
sl@0
|
206 |
to aDestPtr 32 bpp buffer.
|
sl@0
|
207 |
@internalComponent
|
sl@0
|
208 |
@pre aCount > 0
|
sl@0
|
209 |
@param aSrcPtr It points to the source pixel
|
sl@0
|
210 |
@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
|
sl@0
|
211 |
@param aCount How many times the pixel value should be copied
|
sl@0
|
212 |
@return The updated aDestPtr
|
sl@0
|
213 |
*/
|
sl@0
|
214 |
template <>
|
sl@0
|
215 |
TUint8* TScanLineDecompressor<E3bpp, E4bpp>::CopyPixel(TUint8* aDestPtr,
|
sl@0
|
216 |
const TUint8* aSrcPtr,
|
sl@0
|
217 |
TInt aCount) const
|
sl@0
|
218 |
{
|
sl@0
|
219 |
const TUint8 b1 = *aSrcPtr;
|
sl@0
|
220 |
const TUint8 b2 = *(aSrcPtr + 1);
|
sl@0
|
221 |
const TUint8 b3 = *(aSrcPtr + 2);
|
sl@0
|
222 |
|
sl@0
|
223 |
if((reinterpret_cast<TUint32>(aDestPtr) & 0x3)== 0) // the start address is word aligned
|
sl@0
|
224 |
{
|
sl@0
|
225 |
const TUint32 pixel = 0xFF000000 | (b3 << 16) | (b2 << 8) | b1; //it is more accurate to equalize to 0xff,
|
sl@0
|
226 |
//as top byte could correspond an alpha channel
|
sl@0
|
227 |
TUint32* destPtr32 = reinterpret_cast <TUint32*>(aDestPtr);
|
sl@0
|
228 |
TInt blocksOf16 = ((aCount + 0x0f) >> 4); // number of blocks of upto 16 words to write
|
sl@0
|
229 |
// the first iteration writes 1 to 15 words
|
sl@0
|
230 |
switch (aCount & 0x0f)
|
sl@0
|
231 |
{ // note that case statements intentionally cascade
|
sl@0
|
232 |
case 0:
|
sl@0
|
233 |
do { // second and subsequent iterations always write 16 words
|
sl@0
|
234 |
*destPtr32++ = pixel;
|
sl@0
|
235 |
case 15:
|
sl@0
|
236 |
*destPtr32++ = pixel;
|
sl@0
|
237 |
case 14:
|
sl@0
|
238 |
*destPtr32++ = pixel;
|
sl@0
|
239 |
case 13:
|
sl@0
|
240 |
*destPtr32++ = pixel;
|
sl@0
|
241 |
case 12:
|
sl@0
|
242 |
*destPtr32++ = pixel;
|
sl@0
|
243 |
case 11:
|
sl@0
|
244 |
*destPtr32++ = pixel;
|
sl@0
|
245 |
case 10:
|
sl@0
|
246 |
*destPtr32++ = pixel;
|
sl@0
|
247 |
case 9:
|
sl@0
|
248 |
*destPtr32++ = pixel;
|
sl@0
|
249 |
case 8:
|
sl@0
|
250 |
*destPtr32++ = pixel;
|
sl@0
|
251 |
case 7:
|
sl@0
|
252 |
*destPtr32++ = pixel;
|
sl@0
|
253 |
case 6:
|
sl@0
|
254 |
*destPtr32++ = pixel;
|
sl@0
|
255 |
case 5:
|
sl@0
|
256 |
*destPtr32++ = pixel;
|
sl@0
|
257 |
case 4:
|
sl@0
|
258 |
*destPtr32++ = pixel;
|
sl@0
|
259 |
case 3:
|
sl@0
|
260 |
*destPtr32++ = pixel;
|
sl@0
|
261 |
case 2:
|
sl@0
|
262 |
*destPtr32++ = pixel;
|
sl@0
|
263 |
case 1:
|
sl@0
|
264 |
*destPtr32++ = pixel;
|
sl@0
|
265 |
} while(--blocksOf16 > 0);
|
sl@0
|
266 |
}
|
sl@0
|
267 |
|
sl@0
|
268 |
return reinterpret_cast <TUint8*>(destPtr32);
|
sl@0
|
269 |
}
|
sl@0
|
270 |
|
sl@0
|
271 |
while(aCount--)
|
sl@0
|
272 |
{
|
sl@0
|
273 |
*aDestPtr++ = b1;
|
sl@0
|
274 |
*aDestPtr++ = b2;
|
sl@0
|
275 |
*aDestPtr++ = b3;
|
sl@0
|
276 |
*aDestPtr++ = 0xff; //it is more accurate to equalize to 0xff, as top byte
|
sl@0
|
277 |
//could correspond an alpha channel
|
sl@0
|
278 |
}
|
sl@0
|
279 |
return aDestPtr;
|
sl@0
|
280 |
}
|
sl@0
|
281 |
|
sl@0
|
282 |
/**
|
sl@0
|
283 |
The method gets the 24 bpp pixel value pointed by aSrcPtr and copies it aCount times
|
sl@0
|
284 |
to aDestPtr 32 bpp buffer.
|
sl@0
|
285 |
@internalComponent
|
sl@0
|
286 |
@pre aCount > 0
|
sl@0
|
287 |
@param aSrcPtr It points to the source pixel
|
sl@0
|
288 |
@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
|
sl@0
|
289 |
@param aCount How many times the pixel value should be copied
|
sl@0
|
290 |
@return The updated aDestPtr
|
sl@0
|
291 |
*/
|
sl@0
|
292 |
template <>
|
sl@0
|
293 |
TUint8* TScanLineDecompressor<E3bpp, E4bpp>::CopyBlockPixel(TUint8* aDestPtr,
|
sl@0
|
294 |
const TUint8* aSrcPtr,
|
sl@0
|
295 |
TInt aCount) const
|
sl@0
|
296 |
{
|
sl@0
|
297 |
while(aCount--)
|
sl@0
|
298 |
{
|
sl@0
|
299 |
*aDestPtr++ = *aSrcPtr++;
|
sl@0
|
300 |
*aDestPtr++ = *aSrcPtr++;
|
sl@0
|
301 |
*aDestPtr++ = *aSrcPtr++;
|
sl@0
|
302 |
*aDestPtr++ = 0xff; //it is more accurate to equalize to 0xff, as top byte
|
sl@0
|
303 |
//could correspond an alpha channel
|
sl@0
|
304 |
}
|
sl@0
|
305 |
return aDestPtr;
|
sl@0
|
306 |
}
|
sl@0
|
307 |
|
sl@0
|
308 |
/**
|
sl@0
|
309 |
The method should never be executed.
|
sl@0
|
310 |
Introduced to prevent CCover compiler from failing.
|
sl@0
|
311 |
@internalComponent
|
sl@0
|
312 |
@return The unchanged aDestPtr
|
sl@0
|
313 |
*/
|
sl@0
|
314 |
template <>
|
sl@0
|
315 |
TUint8* TScanLineDecompressor<E2bpp, E2bpp>::CopyBlockPixel(TUint8* aDestPtr,
|
sl@0
|
316 |
const TUint8* /*aSrcPtr*/,
|
sl@0
|
317 |
TInt /*aCount*/) const
|
sl@0
|
318 |
{
|
sl@0
|
319 |
return aDestPtr;
|
sl@0
|
320 |
}
|
sl@0
|
321 |
|
sl@0
|
322 |
/**
|
sl@0
|
323 |
The method should never be executed.
|
sl@0
|
324 |
Introduced to prevent CCover compiler from failing.
|
sl@0
|
325 |
@internalComponent
|
sl@0
|
326 |
@return The unchanged aDestPtr
|
sl@0
|
327 |
*/
|
sl@0
|
328 |
template <>
|
sl@0
|
329 |
TUint8* TScanLineDecompressor<E3bpp, E3bpp>::CopyBlockPixel(TUint8* aDestPtr,
|
sl@0
|
330 |
const TUint8* /*aSrcPtr*/,
|
sl@0
|
331 |
TInt /*aCount*/) const
|
sl@0
|
332 |
{
|
sl@0
|
333 |
return aDestPtr;
|
sl@0
|
334 |
}
|
sl@0
|
335 |
|
sl@0
|
336 |
/**
|
sl@0
|
337 |
The method should never be executed.
|
sl@0
|
338 |
Introduced to prevent CCover compiler from failing.
|
sl@0
|
339 |
@internalComponent
|
sl@0
|
340 |
@return The unchanged aDestPtr
|
sl@0
|
341 |
*/
|
sl@0
|
342 |
template <>
|
sl@0
|
343 |
TUint8* TScanLineDecompressor<E4bpp, E4bpp>::CopyBlockPixel(TUint8* aDestPtr,
|
sl@0
|
344 |
const TUint8* /*aSrcPtr*/,
|
sl@0
|
345 |
TInt /*aCount*/) const
|
sl@0
|
346 |
{
|
sl@0
|
347 |
return aDestPtr;
|
sl@0
|
348 |
}
|