|
1 /* |
|
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "AknBitmapMirrorUtils.h" |
|
20 #include <bitdev.h> |
|
21 |
|
22 enum |
|
23 { |
|
24 EAknNoMirroring = 0, |
|
25 EAknVerticalMirroring, |
|
26 EAknHorizontalMirroring |
|
27 }; |
|
28 |
|
29 void AknBitmapMirrorUtils::LoadHorizontalMirroredBitmapL(CFbsBitmap* aBitmap, const TDesC& aFileName,TInt32 aId) |
|
30 { |
|
31 LoadPartialBitmapL(aBitmap, aFileName,aId, KWholeBitmapRect, ETrue); |
|
32 } |
|
33 |
|
34 void AknBitmapMirrorUtils::LoadPartialBitmapL(CFbsBitmap* aBitmap, const TDesC& aFileName,TInt32 aId, TRect aRect, TBool aMirrorHorizontally) |
|
35 { |
|
36 CFbsBitmap* destinationBitmap = aBitmap; |
|
37 User::LeaveIfNull(destinationBitmap); |
|
38 |
|
39 CFbsBitmap* sourceBitmap = new (ELeave) CFbsBitmap(); |
|
40 CleanupStack::PushL(sourceBitmap); |
|
41 User::LeaveIfError(sourceBitmap->Load(aFileName, aId, ETrue)); |
|
42 TSize sourceBitmapSize = sourceBitmap->SizeInPixels(); |
|
43 |
|
44 TRect sourceRect = TRect(aRect); |
|
45 if (sourceRect == KWholeBitmapRect) |
|
46 { |
|
47 sourceRect.iTl.iX = 0; |
|
48 sourceRect.iTl.iY = 0; |
|
49 sourceRect.iBr.iX = sourceBitmapSize.iWidth; |
|
50 sourceRect.iBr.iY = sourceBitmapSize.iHeight; |
|
51 } |
|
52 |
|
53 TSize destinationBitmapSize(sourceRect.Width(), sourceRect.Height()); |
|
54 User::LeaveIfError(destinationBitmap->Create(destinationBitmapSize, sourceBitmap->DisplayMode())); |
|
55 |
|
56 CFbsBitmapDevice* destinationDevice = CFbsBitmapDevice::NewL( destinationBitmap ); |
|
57 CleanupStack::PushL(destinationDevice); |
|
58 |
|
59 CFbsBitGc* destinationGc; |
|
60 User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) ); |
|
61 |
|
62 if (aMirrorHorizontally) |
|
63 { |
|
64 TRect sourceBitmapBlittingRect( sourceRect.iTl.iX,sourceRect.iTl.iY,sourceRect.iTl.iX + 1,sourceRect.iBr.iY ); |
|
65 |
|
66 for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- ) |
|
67 { |
|
68 destinationGc->BitBlt( TPoint(xPos,0), sourceBitmap, sourceBitmapBlittingRect ); |
|
69 sourceBitmapBlittingRect.iTl.iX++; |
|
70 sourceBitmapBlittingRect.iBr.iX++; |
|
71 } |
|
72 } |
|
73 else |
|
74 { |
|
75 destinationGc->BitBlt( TPoint(0,0), sourceBitmap, sourceRect ); |
|
76 } |
|
77 |
|
78 delete destinationGc; |
|
79 CleanupStack::PopAndDestroy(2); // sourceBitmap, destinationDevice |
|
80 } |
|
81 |
|
82 CFbsBitmap* AknBitmapMirrorUtils::HorizontallyMirrorBitmapL( CFbsBitmap* aBitmap ) |
|
83 { |
|
84 return PartialBitmapL( aBitmap, KWholeBitmapRect, ETrue ); |
|
85 } |
|
86 |
|
87 CFbsBitmap* AknBitmapMirrorUtils::PartialBitmapL( CFbsBitmap* aBitmap, TRect aRect, TBool aMirrorHorizontally ) |
|
88 { |
|
89 User::LeaveIfNull(aBitmap); |
|
90 CFbsBitmap* tmpBitmap = NULL; |
|
91 TSize sourceBitmapSize = aBitmap->SizeInPixels(); |
|
92 |
|
93 TRect sourceRect = TRect(aRect); |
|
94 if ( sourceRect == KWholeBitmapRect ) |
|
95 { |
|
96 sourceRect.iTl.iX = 0; |
|
97 sourceRect.iTl.iY = 0; |
|
98 sourceRect.iBr.iX = sourceBitmapSize.iWidth; |
|
99 sourceRect.iBr.iY = sourceBitmapSize.iHeight; |
|
100 if (aMirrorHorizontally) |
|
101 tmpBitmap = CreateBitmapOptimizedL(aBitmap, EAknHorizontalMirroring); |
|
102 else |
|
103 tmpBitmap = CreateBitmapOptimizedL(aBitmap, EAknNoMirroring); |
|
104 } |
|
105 else |
|
106 { |
|
107 // Check rect sanity |
|
108 if ( sourceRect.iBr.iX > sourceBitmapSize.iWidth || sourceRect.iBr.iX <= 0 ) |
|
109 { |
|
110 sourceRect.iBr.iX = sourceBitmapSize.iWidth; |
|
111 } |
|
112 if ( sourceRect.iBr.iY > sourceBitmapSize.iHeight || sourceRect.iBr.iY <= 0 ) |
|
113 { |
|
114 sourceRect.iBr.iY = sourceBitmapSize.iHeight; |
|
115 } |
|
116 if ( sourceRect.iTl.iX >= sourceBitmapSize.iWidth || sourceRect.iTl.iX < 0) |
|
117 { |
|
118 sourceRect.iTl.iX = 0; |
|
119 } |
|
120 if ( sourceRect.iTl.iY >= sourceBitmapSize.iHeight || sourceRect.iTl.iY < 0) |
|
121 { |
|
122 sourceRect.iTl.iY = 0; |
|
123 } |
|
124 TSize destinationBitmapSize = TSize( sourceRect.Width(), sourceRect.Height() ); |
|
125 |
|
126 // get a copy of wanted rect of source bitmap to tmpBitmap |
|
127 tmpBitmap = new (ELeave) CFbsBitmap(); |
|
128 CleanupStack::PushL( tmpBitmap ); |
|
129 |
|
130 User::LeaveIfError( tmpBitmap->Create( destinationBitmapSize, aBitmap->DisplayMode() ) ); |
|
131 |
|
132 CFbsBitmapDevice* destinationDevice = CFbsBitmapDevice::NewL( tmpBitmap ); |
|
133 CleanupStack::PushL( destinationDevice ); |
|
134 |
|
135 CFbsBitGc* destinationGc; |
|
136 User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) ); |
|
137 |
|
138 if ( aMirrorHorizontally ) |
|
139 { |
|
140 TRect sourceBitmapBlittingRect( sourceRect.iTl.iX, sourceRect.iTl.iY, |
|
141 sourceRect.iTl.iX + 1, sourceRect.iBr.iY ); |
|
142 |
|
143 for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- ) |
|
144 { |
|
145 destinationGc->BitBlt( TPoint(xPos,0), aBitmap, sourceBitmapBlittingRect ); |
|
146 sourceBitmapBlittingRect.iTl.iX++; |
|
147 sourceBitmapBlittingRect.iBr.iX++; |
|
148 } |
|
149 } |
|
150 else |
|
151 { |
|
152 destinationGc->BitBlt( TPoint(0,0), aBitmap, sourceRect ); |
|
153 } |
|
154 |
|
155 delete destinationGc; |
|
156 CleanupStack::PopAndDestroy(); // destinationDevice |
|
157 CleanupStack::Pop(); // tmpBitmap |
|
158 } |
|
159 |
|
160 return tmpBitmap; |
|
161 } |
|
162 |
|
163 CFbsBitmap* AknBitmapMirrorUtils::CreateMirroredBitmapL(CFbsBitmap* aSourceBitmap, TBool aVerticalMirror, TBool aHorizontalMirror) |
|
164 { |
|
165 CFbsBitmap* verticalMirroredBitmap = NULL; |
|
166 CFbsBitmap* horizontalMirroredBitmap = NULL; |
|
167 |
|
168 if (aVerticalMirror) |
|
169 { |
|
170 verticalMirroredBitmap = CreateBitmapOptimizedL(aSourceBitmap, EAknVerticalMirroring); |
|
171 } |
|
172 |
|
173 if (aHorizontalMirror) |
|
174 { |
|
175 if (verticalMirroredBitmap) |
|
176 { |
|
177 CleanupStack::PushL(verticalMirroredBitmap); |
|
178 horizontalMirroredBitmap = CreateBitmapOptimizedL(verticalMirroredBitmap, EAknHorizontalMirroring); |
|
179 CleanupStack::PopAndDestroy(); // verticalMirroredBitmap |
|
180 verticalMirroredBitmap = NULL; |
|
181 } |
|
182 else |
|
183 { |
|
184 horizontalMirroredBitmap = CreateBitmapOptimizedL(aSourceBitmap, EAknHorizontalMirroring); |
|
185 } |
|
186 } |
|
187 |
|
188 |
|
189 if (!aHorizontalMirror && !aVerticalMirror) |
|
190 { |
|
191 verticalMirroredBitmap = CreateBitmapOptimizedL(aSourceBitmap, EAknNoMirroring); |
|
192 } |
|
193 |
|
194 if (verticalMirroredBitmap) |
|
195 { |
|
196 return verticalMirroredBitmap; |
|
197 } |
|
198 else |
|
199 { |
|
200 return horizontalMirroredBitmap; |
|
201 } |
|
202 |
|
203 |
|
204 } |
|
205 |
|
206 |
|
207 CFbsBitmap* AknBitmapMirrorUtils::CreateBitmapL(CFbsBitmap* aSourceBitmap, TInt aMirrorDirection) |
|
208 { |
|
209 User::LeaveIfNull(aSourceBitmap); |
|
210 CFbsBitmap* destinationBitmap = new (ELeave) CFbsBitmap(); |
|
211 CleanupStack::PushL(destinationBitmap); |
|
212 |
|
213 TSize sourceBitmapSize = aSourceBitmap->SizeInPixels(); |
|
214 TRect sourceRect = TRect(TPoint(0,0), sourceBitmapSize); |
|
215 TSize destinationBitmapSize(sourceRect.Width(), sourceRect.Height()); |
|
216 |
|
217 User::LeaveIfError(destinationBitmap->Create(destinationBitmapSize, aSourceBitmap->DisplayMode())); |
|
218 |
|
219 CFbsBitmapDevice* destinationDevice = CFbsBitmapDevice::NewL( destinationBitmap ); |
|
220 CleanupStack::PushL(destinationDevice); |
|
221 |
|
222 CFbsBitGc* destinationGc; |
|
223 User::LeaveIfError( destinationDevice->CreateContext( destinationGc ) ); |
|
224 |
|
225 switch (aMirrorDirection) |
|
226 { |
|
227 case EAknVerticalMirroring: |
|
228 { |
|
229 TRect sourceBitmapBlittingRect( sourceRect.iTl.iX,sourceRect.iTl.iY,sourceRect.iBr.iX,sourceRect.iTl.iY + 1 ); |
|
230 for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- ) |
|
231 { |
|
232 destinationGc->BitBlt( TPoint(0,yPos), aSourceBitmap, sourceBitmapBlittingRect ); |
|
233 sourceBitmapBlittingRect.iTl.iY++; |
|
234 sourceBitmapBlittingRect.iBr.iY++; |
|
235 } |
|
236 break; |
|
237 } |
|
238 |
|
239 case EAknHorizontalMirroring: |
|
240 { |
|
241 TRect sourceBitmapBlittingRect( sourceRect.iTl.iX,sourceRect.iTl.iY,sourceRect.iTl.iX + 1,sourceRect.iBr.iY ); |
|
242 for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- ) |
|
243 { |
|
244 destinationGc->BitBlt( TPoint(xPos,0), aSourceBitmap, sourceBitmapBlittingRect ); |
|
245 sourceBitmapBlittingRect.iTl.iX++; |
|
246 sourceBitmapBlittingRect.iBr.iX++; |
|
247 } |
|
248 break; |
|
249 } |
|
250 |
|
251 default: |
|
252 { |
|
253 destinationGc->BitBlt( TPoint(0,0), aSourceBitmap, sourceRect ); |
|
254 break; |
|
255 } |
|
256 } |
|
257 |
|
258 delete destinationGc; |
|
259 CleanupStack::Pop(2); // destinationBitmap, destinationDevice |
|
260 delete destinationDevice; |
|
261 |
|
262 return destinationBitmap; |
|
263 } |
|
264 |
|
265 CFbsBitmap* AknBitmapMirrorUtils::CreateBitmapOptimizedL(CFbsBitmap* aSourceBitmap, TInt aMirrorDirection) |
|
266 { |
|
267 // Check if displaymode is optimized, fallback to non-optimized version if not. |
|
268 TBool fallback = ETrue; |
|
269 TDisplayMode displayMode = aSourceBitmap->DisplayMode(); |
|
270 switch( displayMode ) |
|
271 { |
|
272 case EGray256: |
|
273 case EColor256: |
|
274 case EColor4K: |
|
275 case EColor64K: |
|
276 fallback = EFalse; |
|
277 break; |
|
278 default: |
|
279 fallback = ETrue; |
|
280 } |
|
281 |
|
282 // Check if mirroring mode is supported, fallback to non-optimized version if not. |
|
283 if ((aMirrorDirection != EAknVerticalMirroring) && (aMirrorDirection != EAknHorizontalMirroring)) |
|
284 { |
|
285 fallback = ETrue; |
|
286 } |
|
287 |
|
288 if( fallback ) |
|
289 return CreateBitmapL(aSourceBitmap, aMirrorDirection); |
|
290 |
|
291 // Prepare destination bitmap |
|
292 User::LeaveIfNull(aSourceBitmap); |
|
293 CFbsBitmap* destinationBitmap = new (ELeave) CFbsBitmap(); |
|
294 CleanupStack::PushL(destinationBitmap); |
|
295 |
|
296 TSize sourceBitmapSize = aSourceBitmap->SizeInPixels(); |
|
297 TRect sourceRect = TRect(TPoint(0,0), sourceBitmapSize); |
|
298 TSize destinationBitmapSize(sourceRect.Width(), sourceRect.Height()); |
|
299 |
|
300 User::LeaveIfError(destinationBitmap->Create(destinationBitmapSize, aSourceBitmap->DisplayMode())); |
|
301 |
|
302 // Check source, if rom bitmap or compressed then create uncompressed ram bitmap |
|
303 TBool srcTemporary = EFalse; |
|
304 if( aSourceBitmap->IsRomBitmap() ) |
|
305 { |
|
306 srcTemporary = ETrue; |
|
307 } |
|
308 |
|
309 // Heap lock for FBServ large chunk to prevent background |
|
310 // compression of aSrcBitmap after if IsCompressedInRAM returns EFalse |
|
311 aSourceBitmap->LockHeapLC( ETrue ); // fbsheaplock |
|
312 TBool fbsHeapLock = ETrue; |
|
313 |
|
314 if( aSourceBitmap->IsCompressedInRAM() ) |
|
315 { |
|
316 srcTemporary = ETrue; |
|
317 } |
|
318 if( aSourceBitmap->ExtendedBitmapType() != KNullUid ) |
|
319 { |
|
320 srcTemporary = ETrue; |
|
321 } |
|
322 |
|
323 CFbsBitmap* realSource = aSourceBitmap; |
|
324 if( srcTemporary ) |
|
325 { |
|
326 CleanupStack::PopAndDestroy(); // fbsheaplock |
|
327 fbsHeapLock = EFalse; |
|
328 |
|
329 realSource = new (ELeave) CFbsBitmap(); |
|
330 CleanupStack::PushL( realSource ); |
|
331 User::LeaveIfError( realSource->Create( sourceBitmapSize, aSourceBitmap->DisplayMode() ) ); |
|
332 CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( realSource ); |
|
333 CleanupStack::PushL( dev ); |
|
334 CFbsBitGc* gc = NULL; |
|
335 User::LeaveIfError( dev->CreateContext( gc ) ); |
|
336 CleanupStack::PushL( gc ); |
|
337 gc->BitBlt( TPoint(0,0), aSourceBitmap ); |
|
338 CleanupStack::PopAndDestroy(2); // dev, gc |
|
339 } |
|
340 |
|
341 // Heap lock for FBServ large chunk is only needed with large bitmaps. |
|
342 if (!fbsHeapLock) |
|
343 { |
|
344 if ( realSource->IsLargeBitmap() || destinationBitmap->IsLargeBitmap() ) |
|
345 { |
|
346 destinationBitmap->LockHeapLC( ETrue ); // fbsheaplock |
|
347 } |
|
348 else |
|
349 { |
|
350 CleanupStack::PushL( (TAny*)NULL ); |
|
351 } |
|
352 } |
|
353 |
|
354 TUint32* srcAddress = realSource->DataAddress(); |
|
355 TUint32* trgAddress = destinationBitmap->DataAddress(); |
|
356 |
|
357 if ( displayMode == EColor4K || displayMode == EColor64K ) |
|
358 { |
|
359 TInt srcScanLen16 = CFbsBitmap::ScanLineLength(sourceBitmapSize.iWidth, displayMode) / 2; |
|
360 TInt trgScanLen16 = CFbsBitmap::ScanLineLength(destinationBitmapSize.iWidth, displayMode) / 2; |
|
361 TInt srcScanLen32 = CFbsBitmap::ScanLineLength(sourceBitmapSize.iWidth, displayMode) / 4; |
|
362 TInt trgScanLen32 = CFbsBitmap::ScanLineLength(destinationBitmapSize.iWidth, displayMode) / 4; |
|
363 |
|
364 switch (aMirrorDirection) |
|
365 { |
|
366 case EAknVerticalMirroring: |
|
367 { |
|
368 TUint32* trgAddress32 = trgAddress; |
|
369 TUint32* srcAddress32 = srcAddress; |
|
370 TInt trgPos = 0; |
|
371 for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- ) |
|
372 { |
|
373 srcAddress32 = srcAddress + srcScanLen32*yPos; |
|
374 trgAddress32 = trgAddress + trgScanLen32*trgPos; |
|
375 memcpy(trgAddress32, srcAddress32, srcScanLen32*4); |
|
376 trgPos++; |
|
377 } |
|
378 break; |
|
379 } |
|
380 case EAknHorizontalMirroring: |
|
381 { |
|
382 TUint16* trgAddress16 = reinterpret_cast<TUint16*>(trgAddress); |
|
383 TUint16* srcAddress16 = reinterpret_cast<TUint16*>(srcAddress); |
|
384 TInt xTrgPos = 0; |
|
385 for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- ) |
|
386 { |
|
387 xTrgPos = 0; |
|
388 for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- ) |
|
389 { |
|
390 trgAddress16[xTrgPos] = srcAddress16[xPos]; |
|
391 xTrgPos++; |
|
392 } |
|
393 srcAddress16 += srcScanLen16; |
|
394 trgAddress16 += trgScanLen16; |
|
395 } |
|
396 |
|
397 break; |
|
398 } |
|
399 default: |
|
400 { |
|
401 break; |
|
402 } |
|
403 } |
|
404 } |
|
405 else if( (displayMode==EGray256) || (displayMode==EColor256) ) |
|
406 { |
|
407 TInt srcScanLen8 = CFbsBitmap::ScanLineLength(sourceBitmapSize.iWidth, displayMode); |
|
408 TInt trgScanLen8 = CFbsBitmap::ScanLineLength(destinationBitmapSize.iWidth, displayMode); |
|
409 TInt srcScanLen32 = CFbsBitmap::ScanLineLength(sourceBitmapSize.iWidth, displayMode) / 4; |
|
410 TInt trgScanLen32 = CFbsBitmap::ScanLineLength(destinationBitmapSize.iWidth, displayMode) / 4; |
|
411 |
|
412 switch (aMirrorDirection) |
|
413 { |
|
414 case EAknVerticalMirroring: |
|
415 { |
|
416 TUint32* trgAddress32 = trgAddress; |
|
417 TUint32* srcAddress32 = srcAddress; |
|
418 TInt trgPos = 0; |
|
419 for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- ) |
|
420 { |
|
421 srcAddress32 = srcAddress + srcScanLen32*yPos; |
|
422 trgAddress32 = trgAddress + trgScanLen32*trgPos; |
|
423 memcpy(trgAddress32, srcAddress32, srcScanLen32*4); |
|
424 trgPos++; |
|
425 } |
|
426 break; |
|
427 } |
|
428 case EAknHorizontalMirroring: |
|
429 { |
|
430 TUint8* trgAddress8 = reinterpret_cast<TUint8*>(trgAddress); |
|
431 TUint8* srcAddress8 = reinterpret_cast<TUint8*>(srcAddress); |
|
432 TInt xTrgPos = 0; |
|
433 for ( TInt yPos=destinationBitmapSize.iHeight-1; yPos >= 0; yPos-- ) |
|
434 { |
|
435 xTrgPos = 0; |
|
436 for ( TInt xPos=destinationBitmapSize.iWidth-1; xPos >= 0; xPos-- ) |
|
437 { |
|
438 trgAddress8[xTrgPos] = srcAddress8[xPos]; |
|
439 xTrgPos++; |
|
440 } |
|
441 srcAddress8 += srcScanLen8; |
|
442 trgAddress8 += trgScanLen8; |
|
443 } |
|
444 break; |
|
445 } |
|
446 default: |
|
447 { |
|
448 break; |
|
449 } |
|
450 } |
|
451 } |
|
452 |
|
453 CleanupStack::PopAndDestroy(); // fbsheaplock |
|
454 |
|
455 if( srcTemporary ) |
|
456 { |
|
457 CleanupStack::PopAndDestroy(); // realSource |
|
458 } |
|
459 |
|
460 CleanupStack::Pop(); // destinationBitmap |
|
461 return destinationBitmap; |
|
462 } |