|
1 /* |
|
2 * Copyright (c) 2005 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: Image loader and scaler |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "CCAImageLoader.h" |
|
20 #include "MCAChatInterface.h" |
|
21 #include "CCAContentMessage.h" |
|
22 |
|
23 #include "ChatDebugPrint.h" |
|
24 #include "chatdebugassert.h" |
|
25 #include "impsbuilddefinitions.h" |
|
26 |
|
27 #include "mcaimpsfactory.h" |
|
28 #include "mcaimpsimclient.h" |
|
29 #include "wvengutils.h" |
|
30 #include "imnginternalcrkeys.h" |
|
31 #include "imprivatecrkeys.h" |
|
32 #include "imvariant.hrh" |
|
33 |
|
34 #include <ImageConversion.h> |
|
35 #include <BitmapTransforms.h> |
|
36 #include <s32file.h> |
|
37 |
|
38 // CONSTANTS |
|
39 const TInt KChatCustomBitmapWidth = 320; |
|
40 const TInt KChatCustomBitmapHeight = 240; |
|
41 |
|
42 // From ICL documentation: |
|
43 // "all decoder plugins also support thumbnail decodes with ratios of 1:2, 1:4 and 1:8." |
|
44 const TInt KDecodeScaleRatioMin = 2; |
|
45 const TInt KDecodeScaleRatioMax = 8; |
|
46 |
|
47 |
|
48 //----------------------------------------------------------------------------- |
|
49 // CCAImageLoader::CCAImageLoader |
|
50 // ( Other items commented in header ) |
|
51 //----------------------------------------------------------------------------- |
|
52 CCAImageLoader::CCAImageLoader( |
|
53 MCAChatInterface& aChatInterface, MCAImpsFactory& aImpsFactory ) |
|
54 : CActive( CActive::EPriorityLow ), |
|
55 iChatInterface( aChatInterface ), |
|
56 iImpsFactory( aImpsFactory ) |
|
57 { |
|
58 CHAT_DP_FUNC_ENTER( "CCAImageLoader::CCAImageLoader" ); |
|
59 CActiveScheduler::Add( this ); |
|
60 CHAT_DP_FUNC_DONE( "CCAImageLoader::CCAImageLoader" ); |
|
61 } |
|
62 |
|
63 //----------------------------------------------------------------------------- |
|
64 // CCAImageLoader::CCAImageLoader |
|
65 // ( Other items commented in header ) |
|
66 //----------------------------------------------------------------------------- |
|
67 CCAImageLoader::~CCAImageLoader() |
|
68 { |
|
69 CHAT_DP_FUNC_ENTER( "CCAImageLoader::~CCAImageLoader" ); |
|
70 iFs.Close(); |
|
71 |
|
72 delete iDecoder; |
|
73 delete iScaler; |
|
74 delete iEncoder; |
|
75 delete iBitmap; |
|
76 delete iContent; |
|
77 |
|
78 iMessages.Close(); |
|
79 |
|
80 CHAT_DP_FUNC_DONE( "CCAImageLoader::~CCAImageLoader" ); |
|
81 } |
|
82 |
|
83 //----------------------------------------------------------------------------- |
|
84 // CCAImageLoader::NewL |
|
85 // ( Other items commented in header ) |
|
86 //----------------------------------------------------------------------------- |
|
87 CCAImageLoader* CCAImageLoader::NewL( MCAChatInterface& aChatInterface, |
|
88 MCAImpsFactory& aImpsFactory ) |
|
89 { |
|
90 CHAT_DP_FUNC_ENTER( "CCAImageLoader::NewL" ); |
|
91 CCAImageLoader* self = |
|
92 new ( ELeave ) CCAImageLoader( aChatInterface, aImpsFactory ); |
|
93 CleanupStack::PushL( self ); |
|
94 self->ConstructL(); |
|
95 CleanupStack::Pop( self ); |
|
96 CHAT_DP_FUNC_DONE( "CCAImageLoader::NewL" ); |
|
97 return self; |
|
98 } |
|
99 |
|
100 //----------------------------------------------------------------------------- |
|
101 // CCAImageLoader::ConstructL |
|
102 // ( Other items commented in header ) |
|
103 //----------------------------------------------------------------------------- |
|
104 void CCAImageLoader::ConstructL() |
|
105 { |
|
106 CHAT_DP_FUNC_ENTER( "CCAImageLoader::ConstructL" ); |
|
107 User::LeaveIfError( iFs.Connect() ); |
|
108 |
|
109 iSendNotScalable = WVEngUtils::CRKeyL( KCRUidIMVariation, KIMVariationKey ) |
|
110 & EIMFeatSendNotScalable; |
|
111 CHAT_DP_FUNC_DONE( "CCAImageLoader::ConstructL" ); |
|
112 } |
|
113 |
|
114 |
|
115 //----------------------------------------------------------------------------- |
|
116 // CCAImageLoader::RunL |
|
117 // ( Other items commented in header ) |
|
118 //----------------------------------------------------------------------------- |
|
119 void CCAImageLoader::RunL() |
|
120 { |
|
121 CHAT_DP_FUNC_ENTER( "CCAImageLoader::RunL" ); |
|
122 TInt status = iStatus.Int(); |
|
123 CHAT_DP( D_CHAT_LIT( "Status %d" ), status ); |
|
124 switch ( status ) |
|
125 { |
|
126 case KErrUnderflow: |
|
127 { |
|
128 if ( iDecoder ) |
|
129 { |
|
130 CHAT_DP( D_CHAT_LIT( "Continue converting." ) ); |
|
131 iStatus = KRequestPending; |
|
132 iDecoder->ContinueConvert( &iStatus ); |
|
133 } |
|
134 else |
|
135 { |
|
136 CompleteRequestL(); |
|
137 } |
|
138 break; |
|
139 } |
|
140 case KErrNone: |
|
141 { |
|
142 if ( iDecoder ) |
|
143 { |
|
144 delete iDecoder; |
|
145 iDecoder = NULL; |
|
146 switch ( iCurrentMessage->ContentProcessState() ) |
|
147 { |
|
148 case MCAMessage::EContentNotProcessed: |
|
149 { |
|
150 CHAT_DP( D_CHAT_LIT( "-> Start scaling." ) ); |
|
151 // Decode ready -> Start scaling. |
|
152 iCurrentMessage->SetProcessState( |
|
153 MCAMessage::EBitmapDecoded ); |
|
154 StartProcessingL( *iCurrentMessage ); |
|
155 break; |
|
156 } |
|
157 case MCAMessage::EContentReady: |
|
158 { |
|
159 CHAT_DP( |
|
160 D_CHAT_LIT( "-> Start scaling to thumbnail." ) ); |
|
161 // Decode ready -> Start making thumbnail. |
|
162 iCurrentMessage->SetProcessState( |
|
163 MCAMessage::EContentDecoded ); |
|
164 StartProcessingL( *iCurrentMessage ); |
|
165 break; |
|
166 } |
|
167 default: |
|
168 { |
|
169 iStatus = KErrNotSupported; |
|
170 CompleteRequestL(); |
|
171 break; |
|
172 } |
|
173 } |
|
174 |
|
175 } |
|
176 else if ( iScaler ) |
|
177 { |
|
178 // scaling ready -> start encoding |
|
179 delete iScaler; |
|
180 iScaler = NULL; |
|
181 switch ( iCurrentMessage->ContentProcessState() ) |
|
182 { |
|
183 case MCAMessage::EBitmapDecoded: |
|
184 { |
|
185 CHAT_DP( D_CHAT_LIT( "-> Start encoding." ) ); |
|
186 iCurrentMessage->SetProcessState( |
|
187 MCAMessage::EBitmapScaled ); |
|
188 StartProcessingL( *iCurrentMessage ); |
|
189 break; |
|
190 } |
|
191 case MCAMessage::EContentDecoded: |
|
192 { |
|
193 CHAT_DP( D_CHAT_LIT( "Thumbnail ready." ) ); |
|
194 CCAContentMessage* message = |
|
195 static_cast< CCAContentMessage* >( iCurrentMessage ); |
|
196 message->SetThumbnail( iBitmap ); |
|
197 iBitmap = NULL; |
|
198 iCurrentMessage->SetProcessState( |
|
199 MCAMessage::EThumbnailReady ); |
|
200 CompleteRequestL(); |
|
201 break; |
|
202 } |
|
203 default: |
|
204 { |
|
205 iStatus = KErrNotSupported; |
|
206 CompleteRequestL(); |
|
207 break; |
|
208 } |
|
209 } |
|
210 } |
|
211 else if ( iEncoder ) |
|
212 { |
|
213 CHAT_DP( D_CHAT_LIT( "Content ready. -> Stop processing." ) ); |
|
214 delete iEncoder; |
|
215 iEncoder = NULL; |
|
216 iCurrentMessage->SetProcessState( MCAMessage::EContentReady ); |
|
217 iCurrentMessage->SetContentData( iContent ); |
|
218 iContent = NULL; |
|
219 delete iBitmap; |
|
220 iBitmap = NULL; |
|
221 CompleteRequestL(); |
|
222 } |
|
223 else |
|
224 { |
|
225 iStatus = KErrNotSupported; |
|
226 CompleteRequestL(); |
|
227 } |
|
228 break; |
|
229 } |
|
230 case KErrNoMemory: |
|
231 { |
|
232 // RunError will handle this case |
|
233 User::Leave( KErrNoMemory ); |
|
234 } |
|
235 default: |
|
236 { |
|
237 CompleteRequestL(); |
|
238 break; |
|
239 } |
|
240 } |
|
241 CHAT_DP_FUNC_DONE( "CCAImageLoader::RunL" ); |
|
242 } |
|
243 |
|
244 //----------------------------------------------------------------------------- |
|
245 // CCAImageLoader::DoCancel |
|
246 // ( Other items commented in header ) |
|
247 //----------------------------------------------------------------------------- |
|
248 void CCAImageLoader::DoCancel() |
|
249 { |
|
250 CHAT_DP_FUNC_ENTER( "CCAImageLoader::DoCancel" ); |
|
251 |
|
252 ClearState(); |
|
253 iCurrentMessage->HandleProcessingComplete( *this, iStatus.Int() ); |
|
254 CHAT_DP_FUNC_DONE( "CCAImageLoader::DoCancel" ); |
|
255 } |
|
256 |
|
257 //----------------------------------------------------------------------------- |
|
258 // CCAImageLoader::RunError |
|
259 // ( Other items commented in header ) |
|
260 //----------------------------------------------------------------------------- |
|
261 TInt CCAImageLoader::RunError( TInt aError ) |
|
262 { |
|
263 CHAT_DP_FUNC_ENTER( "CCAImageLoader::RunError" ); |
|
264 if ( IsActive() ) |
|
265 { |
|
266 iStatus = aError; |
|
267 Cancel(); |
|
268 } |
|
269 |
|
270 if ( aError == KErrNoMemory ) |
|
271 { |
|
272 CActiveScheduler::Current()->Error( KErrNoMemory ); |
|
273 } |
|
274 |
|
275 // Clean up and reset all pending messages |
|
276 ClearState(); |
|
277 TRAP_IGNORE( ResetProcessingL( aError ) ); |
|
278 |
|
279 CHAT_DP_FUNC_DONE( "CCAImageLoader::RunError" ); |
|
280 return KErrNone; |
|
281 } |
|
282 |
|
283 //----------------------------------------------------------------------------- |
|
284 // CCAImageLoader::RequestProcessing |
|
285 // ( Other items commented in header ) |
|
286 //----------------------------------------------------------------------------- |
|
287 void CCAImageLoader::RequestProcessingL( MCAMessage& aMessage ) |
|
288 { |
|
289 CHAT_DP_FUNC_ENTER( "CCAImageLoader::RequestProcessingL" ); |
|
290 // Append to scheduler |
|
291 iMessages.AppendL( &aMessage ); |
|
292 LaunchProcessingL(); |
|
293 CHAT_DP_FUNC_DONE( "CCAImageLoader::RequestProcessingL" ); |
|
294 } |
|
295 |
|
296 //----------------------------------------------------------------------------- |
|
297 // CCAImageLoader::StartProcessing |
|
298 // ( Other items commented in header ) |
|
299 //----------------------------------------------------------------------------- |
|
300 void CCAImageLoader::StartProcessingL( MCAMessage& aMessage ) |
|
301 { |
|
302 CHAT_DP_FUNC_ENTER( "CCAImageLoader::StartProcessingL" ); |
|
303 // File -> bitmap |
|
304 // bitmap -> scaled bitmap |
|
305 // scaled bitmap -> encoded content |
|
306 |
|
307 iCurrentMessage = &aMessage; |
|
308 switch ( aMessage.ContentProcessState() ) |
|
309 { |
|
310 case MCAMessage::EContentNotProcessed: // File -> bitmap |
|
311 { |
|
312 __CHAT_ASSERT_DEBUG( !iDecoder ); |
|
313 iDecoder = CImageDecoder::FileNewL( iFs, aMessage.Text() ); |
|
314 |
|
315 TSize origSize( iDecoder->FrameInfo().iOverallSizeInPixels ); |
|
316 ScaleSize( origSize, iTargetSize ); |
|
317 TBool fullyScaleable( iDecoder->FrameInfo().iFlags & TFrameInfo::EFullyScaleable ); |
|
318 |
|
319 TInt frameCount = iDecoder->FrameCount(); |
|
320 if ( frameCount > 1 && iSendNotScalable ) |
|
321 { |
|
322 // Animated gif, try to send file as it is |
|
323 // Animation would be lost in decoding/scaling process |
|
324 |
|
325 delete iDecoder; // Delete -> unlocks image file |
|
326 iDecoder = NULL; |
|
327 |
|
328 // Open file |
|
329 RFile file; |
|
330 User::LeaveIfError( file.Open( iFs, aMessage.Text(), EFileRead ) ); |
|
331 CleanupClosePushL( file ); |
|
332 |
|
333 // Get file size |
|
334 TInt fileSize = 0; |
|
335 User::LeaveIfError( file.Size( fileSize ) ); |
|
336 |
|
337 // Check file size, if bigger than max transaction content -> leave |
|
338 if ( fileSize > |
|
339 iImpsFactory.CreateImClientL()->MaxTransactionContentLengthL() ) |
|
340 { |
|
341 User::Leave( KErrOverflow ); |
|
342 } |
|
343 |
|
344 // Get file content |
|
345 HBufC8* content = HBufC8::NewLC( fileSize ); |
|
346 TPtr8 ptr( content->Des() ); |
|
347 User::LeaveIfError( file.Read( ptr, fileSize ) ); |
|
348 |
|
349 // Set content to message, ownership is transferred |
|
350 CleanupStack::Pop( content ); |
|
351 CleanupStack::PopAndDestroy(); // file.Close() |
|
352 iCurrentMessage->SetProcessState( MCAMessage::EContentReady ); |
|
353 iCurrentMessage->SetContentData( content ); |
|
354 |
|
355 // Complete |
|
356 CompleteRequestL(); |
|
357 break; |
|
358 } |
|
359 |
|
360 TSize decodeSize( DecodeSize( origSize, iTargetSize, fullyScaleable ) ); |
|
361 |
|
362 __CHAT_ASSERT_DEBUG( !iBitmap ); |
|
363 iBitmap = new ( ELeave ) CFbsBitmap(); |
|
364 User::LeaveIfError( iBitmap->Create( decodeSize, |
|
365 iDecoder->FrameInfo().iFrameDisplayMode ) ); |
|
366 iDecoder->Convert( &iStatus, *iBitmap ); |
|
367 if ( !IsActive() ) |
|
368 { |
|
369 SetActive(); |
|
370 } |
|
371 break; |
|
372 } |
|
373 case MCAMessage::EBitmapDecoded: // scale bitmap to size 320x240 |
|
374 { |
|
375 TSize currentSize( iBitmap ? iBitmap->SizeInPixels() : iTargetSize ); |
|
376 |
|
377 if ( currentSize != iTargetSize ) |
|
378 { |
|
379 // bitmap exists and the size is wrong, |
|
380 // we have to scale the bitmap |
|
381 __CHAT_ASSERT_DEBUG( !iScaler ); |
|
382 iScaler = CBitmapScaler::NewL(); |
|
383 iScaler->Scale( &iStatus, *iBitmap, iTargetSize ); |
|
384 if ( !IsActive() ) |
|
385 { |
|
386 SetActive(); |
|
387 } |
|
388 } |
|
389 else |
|
390 { |
|
391 // the size is already correct => skip this step |
|
392 aMessage.SetProcessState( MCAMessage::EBitmapScaled ); |
|
393 StartProcessingL( aMessage ); |
|
394 } |
|
395 break; |
|
396 } |
|
397 case MCAMessage::EBitmapScaled: // encode bitmap for sending |
|
398 { |
|
399 __CHAT_ASSERT_DEBUG( !iEncoder ); |
|
400 iEncoder = CImageEncoder::DataNewL( iContent, aMessage.MimeType() ); |
|
401 iEncoder->Convert( &iStatus, *iBitmap ); |
|
402 if ( !IsActive() ) |
|
403 { |
|
404 SetActive(); |
|
405 } |
|
406 break; |
|
407 } |
|
408 case MCAMessage::EContentReady: // decode bitmap for creating thumbnail |
|
409 { |
|
410 __CHAT_ASSERT_DEBUG( !iDecoder ); |
|
411 iDecoder = CImageDecoder::DataNewL( iFs, aMessage.ContentData() ); |
|
412 |
|
413 CCAContentMessage* message = |
|
414 static_cast< CCAContentMessage* >( iCurrentMessage ); |
|
415 iThumbSize = message->ThumbnailSize(); |
|
416 |
|
417 TSize origSize( iDecoder->FrameInfo().iOverallSizeInPixels ); |
|
418 TBool fullyScaleable( iDecoder->FrameInfo().iFlags & TFrameInfo::EFullyScaleable ); |
|
419 |
|
420 TSize decodeSize( DecodeSize( origSize, iThumbSize, fullyScaleable ) ); |
|
421 |
|
422 __CHAT_ASSERT_DEBUG( !iBitmap ); |
|
423 iBitmap = new ( ELeave ) CFbsBitmap(); |
|
424 User::LeaveIfError( iBitmap->Create( decodeSize, |
|
425 iDecoder->FrameInfo().iFrameDisplayMode ) ); |
|
426 iDecoder->Convert( &iStatus, *iBitmap ); |
|
427 if ( !IsActive() ) |
|
428 { |
|
429 SetActive(); |
|
430 } |
|
431 break; |
|
432 } |
|
433 case MCAMessage::EContentDecoded: // scale bitmap to thumbnail size. |
|
434 { |
|
435 TSize currentSize( iBitmap ? iBitmap->SizeInPixels() : iThumbSize ); |
|
436 |
|
437 if ( currentSize != iThumbSize ) |
|
438 { |
|
439 // bitmap exists and the size is wrong, |
|
440 // we have to scale the bitmap |
|
441 __CHAT_ASSERT_DEBUG( !iScaler ); |
|
442 iScaler = CBitmapScaler::NewL(); |
|
443 iScaler->Scale( &iStatus, *iBitmap, iThumbSize ); |
|
444 if ( !IsActive() ) |
|
445 { |
|
446 SetActive(); |
|
447 } |
|
448 } |
|
449 else |
|
450 { |
|
451 // bitmap size is already correct, |
|
452 // set the thumbnail and complete request |
|
453 CCAContentMessage* message = |
|
454 static_cast< CCAContentMessage* >( iCurrentMessage ); |
|
455 message->SetThumbnail( iBitmap ); |
|
456 iBitmap = NULL; |
|
457 aMessage.SetProcessState( MCAMessage::EThumbnailReady ); |
|
458 CompleteRequestL(); |
|
459 } |
|
460 break; |
|
461 } |
|
462 #ifdef RD_SEND_NOT_SUPPORTED_CONTENT |
|
463 case MCAMessage::EContentNotSupported: |
|
464 case MCAMessage::EContentNotSupportedDrm: |
|
465 case MCAMessage::EContentCorrupted: |
|
466 { |
|
467 RFileReadStream fileStream; |
|
468 User::LeaveIfError( fileStream.Open( iFs, |
|
469 aMessage.Text(), |
|
470 EFileRead ) ); |
|
471 CleanupClosePushL( fileStream ); |
|
472 TInt length = fileStream.Source()->SizeL(); |
|
473 HBufC8* temp = HBufC8::NewLC( length ); |
|
474 TPtr8 ptr( temp->Des() ); |
|
475 fileStream.ReadL( ptr, length ); |
|
476 CleanupStack::Pop( temp ); |
|
477 iCurrentMessage->SetContentData( temp ); |
|
478 CleanupStack::PopAndDestroy(); // fileStream |
|
479 CompleteRequestL(); |
|
480 break; |
|
481 } |
|
482 #endif //RD_SEND_NOT_SUPPORTED_CONTENT |
|
483 default: |
|
484 { |
|
485 // State is not known for processing. Complete it. |
|
486 CompleteRequestL(); |
|
487 break; |
|
488 } |
|
489 } |
|
490 CHAT_DP_FUNC_DONE( "CCAImageLoader::StartProcessingL" ); |
|
491 } |
|
492 |
|
493 //----------------------------------------------------------------------------- |
|
494 // CCAImageLoader::CancelProcessing |
|
495 // ( Other items commented in header ) |
|
496 //----------------------------------------------------------------------------- |
|
497 void CCAImageLoader::CancelProcessing( MCAMessage& aMessage ) |
|
498 { |
|
499 CHAT_DP_FUNC_ENTER( "CCAImageLoader::CancelProcessing" ); |
|
500 if ( iCurrentMessage == &aMessage ) |
|
501 { |
|
502 if ( IsActive() ) |
|
503 { |
|
504 Cancel(); |
|
505 } |
|
506 iCurrentMessage = NULL; |
|
507 } |
|
508 CHAT_DP_FUNC_DONE( "CCAImageLoader::CancelProcessing" ); |
|
509 } |
|
510 |
|
511 //----------------------------------------------------------------------------- |
|
512 // CCAImageLoader::CancelProcessing |
|
513 // ( Other items commented in header ) |
|
514 //----------------------------------------------------------------------------- |
|
515 void CCAImageLoader::RemoveProcessingL( MCAMessage& aMessage ) |
|
516 { |
|
517 CHAT_DP_FUNC_ENTER( "CCAImageLoader::RemoveProcessingL" ); |
|
518 // Cancel if message is processed at the moment. |
|
519 CancelProcessing( aMessage ); |
|
520 // Remove message from scheduler |
|
521 TInt messageIndex( iMessages.Find( &aMessage ) ); |
|
522 if ( messageIndex >= 0 ) |
|
523 { |
|
524 iMessages.Remove( messageIndex ); |
|
525 LaunchProcessingL(); |
|
526 } |
|
527 CHAT_DP_FUNC_DONE( "CCAImageLoader::RemoveProcessingL" ); |
|
528 } |
|
529 |
|
530 //----------------------------------------------------------------------------- |
|
531 // CCAImageLoader::LaunchProcessing |
|
532 // ( Other items commented in header ) |
|
533 //----------------------------------------------------------------------------- |
|
534 void CCAImageLoader::LaunchProcessingL() |
|
535 { |
|
536 CHAT_DP_FUNC_ENTER( "CCAImageLoader::LaunchProcessingL" ); |
|
537 TInt count( iMessages.Count() ); |
|
538 if ( count > 0 && !IsActive() ) |
|
539 { |
|
540 TRAPD( error, StartProcessingL( *iMessages[ 0 ] ) ); |
|
541 if ( error == KErrNoMemory ) |
|
542 { |
|
543 // if no memory: stop the whole process |
|
544 TRAP_IGNORE( ResetProcessingL( error ) ); |
|
545 } |
|
546 else if ( error < 0 ) |
|
547 { |
|
548 iMessages[ 0 ]->SetProcessState( MCAMessage::EContentCorrupted ); |
|
549 TInt ignore; |
|
550 TRAP( ignore, CompleteRequestL() ); |
|
551 User::Leave( error ); |
|
552 } |
|
553 } |
|
554 CHAT_DP_FUNC_DONE( "CCAImageLoader::LaunchProcessingL" ); |
|
555 } |
|
556 |
|
557 //----------------------------------------------------------------------------- |
|
558 // CCAImageLoader::DecodeSize |
|
559 // Scale to nearest (larger or equal) size with ratio 1:1, 1:2, 1:4 or 1:8 |
|
560 //----------------------------------------------------------------------------- |
|
561 TSize CCAImageLoader::DecodeSize( const TSize& aSize, const TSize& aTargetSize, |
|
562 TBool aAnyRatio ) |
|
563 { |
|
564 if ( aAnyRatio || aSize == aTargetSize ) |
|
565 { |
|
566 // decoder can scale to any ratio or the size is already correct |
|
567 return aTargetSize; |
|
568 } |
|
569 |
|
570 // 1:1 is always valid ratio for decode scaling |
|
571 TInt lastValidRatio( 1 ); |
|
572 for ( TInt ratio( KDecodeScaleRatioMin ); ratio <= KDecodeScaleRatioMax; ratio <<= 1 ) |
|
573 { |
|
574 if ( aSize.iWidth % ratio + aSize.iHeight % ratio == 0 ) |
|
575 { |
|
576 // this ratio is valid |
|
577 if ( aSize.iWidth / ratio < aTargetSize.iWidth || |
|
578 aSize.iHeight / ratio < aTargetSize.iHeight ) |
|
579 { |
|
580 // the decoded size was smaller in some dimension, |
|
581 // the last valid ratio should be used |
|
582 break; |
|
583 } |
|
584 |
|
585 // this scale ratio results to greater or equal size |
|
586 lastValidRatio = ratio; |
|
587 } |
|
588 } |
|
589 |
|
590 // return the size scaled with correct ratio |
|
591 return TSize( aSize.iWidth / lastValidRatio, |
|
592 aSize.iHeight / lastValidRatio ); |
|
593 } |
|
594 |
|
595 //----------------------------------------------------------------------------- |
|
596 // CCAImageLoader::ScaleSize |
|
597 // ( Other items commented in header ) |
|
598 //----------------------------------------------------------------------------- |
|
599 TBool CCAImageLoader::ScaleSize( const TSize& aSize, TSize& aNewSize ) |
|
600 { |
|
601 CHAT_DP_FUNC_ENTER( "CCAImageLoader::ScaleSize" ); |
|
602 if ( Max( aSize.iHeight, aSize.iWidth ) > KChatCustomBitmapWidth ) |
|
603 { |
|
604 // scaling needed |
|
605 if ( aSize.iHeight > aSize.iWidth ) |
|
606 { |
|
607 aNewSize.SetSize( KChatCustomBitmapHeight, KChatCustomBitmapWidth ); |
|
608 } |
|
609 else |
|
610 { |
|
611 aNewSize.SetSize( KChatCustomBitmapWidth, KChatCustomBitmapHeight ); |
|
612 } |
|
613 return ETrue; |
|
614 } |
|
615 |
|
616 // old size is correct |
|
617 aNewSize = aSize; |
|
618 CHAT_DP_FUNC_DONE( "CCAImageLoader::ScaleSize" ); |
|
619 return EFalse; |
|
620 } |
|
621 |
|
622 //----------------------------------------------------------------------------- |
|
623 // CCAImageLoader::CompleteRequestL |
|
624 // ( Other items commented in header ) |
|
625 //----------------------------------------------------------------------------- |
|
626 void CCAImageLoader::CompleteRequestL() |
|
627 { |
|
628 CHAT_DP_FUNC_ENTER( "CCAImageLoader::CompleteRequestL" ); |
|
629 iCurrentMessage->HandleProcessingComplete( *this, iStatus.Int() ); |
|
630 TInt index = iMessages.Find( iCurrentMessage ); |
|
631 if ( index >= 0 ) |
|
632 { |
|
633 iMessages.Remove( index ); |
|
634 } |
|
635 iCurrentMessage = NULL; |
|
636 LaunchProcessingL(); |
|
637 CHAT_DP_FUNC_DONE( "CCAImageLoader::CompleteRequestL" ); |
|
638 } |
|
639 |
|
640 //----------------------------------------------------------------------------- |
|
641 // CCAImageLoader::ResetProcessingL |
|
642 // ( Other items commented in header ) |
|
643 //----------------------------------------------------------------------------- |
|
644 void CCAImageLoader::ResetProcessingL( TInt aReason ) |
|
645 { |
|
646 CHAT_DP_FUNC_ENTER( "CCAImageLoader::ResetProcessingL" ); |
|
647 // cancel operation |
|
648 if ( IsActive() ) |
|
649 { |
|
650 iStatus = aReason; |
|
651 Cancel(); |
|
652 } |
|
653 |
|
654 // show note |
|
655 if ( aReason == KErrNoMemory ) |
|
656 { |
|
657 CActiveScheduler::Current()->Error( KErrNoMemory ); |
|
658 } |
|
659 |
|
660 // reset all pending messages |
|
661 TInt count = iMessages.Count(); |
|
662 for ( TInt i = count - 1; i >= 0; --i ) |
|
663 { |
|
664 iMessages[ i ]->SetProcessState( MCAMessage::EContentCorrupted ); |
|
665 iMessages[ i ]->HandleProcessingComplete( *this, aReason ); |
|
666 iMessages.Remove( i ); |
|
667 } |
|
668 CHAT_DP_FUNC_DONE( "CCAImageLoader::ResetProcessingL" ); |
|
669 } |
|
670 |
|
671 //----------------------------------------------------------------------------- |
|
672 // CCAImageLoader::ClearState |
|
673 // ( Other items commented in header ) |
|
674 //----------------------------------------------------------------------------- |
|
675 void CCAImageLoader::ClearState() |
|
676 { |
|
677 CHAT_DP_FUNC_ENTER( "CCAImageLoader::ClearState" ); |
|
678 if ( iScaler ) |
|
679 { |
|
680 CHAT_DP_TXT( "CCAImageLoader::ClearState - Cancel scaler" ); |
|
681 iScaler->Cancel(); |
|
682 delete iScaler; |
|
683 iScaler = NULL; |
|
684 } |
|
685 if ( iDecoder ) |
|
686 { |
|
687 CHAT_DP_TXT( "CCAImageLoader::ClearState - Cancel decoder" ); |
|
688 iDecoder->Cancel(); |
|
689 delete iDecoder; |
|
690 iDecoder = NULL; |
|
691 } |
|
692 if ( iEncoder ) |
|
693 { |
|
694 CHAT_DP_TXT( "CCAImageLoader::ClearState - Cancel encoder" ); |
|
695 iEncoder->Cancel(); |
|
696 delete iEncoder; |
|
697 iEncoder = NULL; |
|
698 } |
|
699 if ( iBitmap ) |
|
700 { |
|
701 delete iBitmap; |
|
702 iBitmap = NULL; |
|
703 } |
|
704 CHAT_DP_FUNC_DONE( "CCAImageLoader::ClearState" ); |
|
705 } |
|
706 |
|
707 // End of file |