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: Screensaver GifAnimation plug-in container source file |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 #include <eikenv.h> |
|
23 #include <w32std.h> |
|
24 #include <e32base.h> |
|
25 #include <e32std.h> |
|
26 |
|
27 #include <IHLImageFactory.h> // IHLImageFactory |
|
28 #include <IHLViewerFactory.h> // IHLViewerFactory |
|
29 #include <MIHLImageViewer.h> // MIHLImageViewer |
|
30 #include <MIHLFileImage.h> // MIHLFileImage |
|
31 #include <MIHLBitmap.h> // MIHLBitmap |
|
32 #include <MIHLImageViewer.h> // MIHLImageViewer |
|
33 #include <MIHLViewerObserver.h> |
|
34 #include <bautils.h> |
|
35 |
|
36 #include "GifAnimationPlugin.h" |
|
37 #include "GifAnimationUtils.h" |
|
38 |
|
39 |
|
40 // ======== MEMBER FUNCTIONS ======== |
|
41 |
|
42 // --------------------------------------------------------------------------- |
|
43 // Instance factory |
|
44 // --------------------------------------------------------------------------- |
|
45 // |
|
46 CGifAnimationPluginControl* CGifAnimationPluginControl::NewL( |
|
47 CCoeControl *aParentControl, |
|
48 MPluginAdapter* aPluginAdapter ) |
|
49 { |
|
50 ASSERT( aPluginAdapter ); |
|
51 DBG_TRACE_FN_BEGIN; |
|
52 CGifAnimationPluginControl* tmp = |
|
53 new ( ELeave )CGifAnimationPluginControl(); |
|
54 CleanupStack::PushL( tmp ); |
|
55 tmp->ConstructL( aParentControl, aPluginAdapter ); |
|
56 CleanupStack::Pop(); |
|
57 DBG_TRACE_FN_END; |
|
58 return tmp; |
|
59 } |
|
60 |
|
61 // --------------------------------------------------------------------------- |
|
62 // 2nd phase constructor |
|
63 // --------------------------------------------------------------------------- |
|
64 // |
|
65 void CGifAnimationPluginControl::ConstructL( CCoeControl* aParentControl, |
|
66 MPluginAdapter* aPluginAdapter ) |
|
67 { |
|
68 DBG_TRACE_FN_BEGIN; |
|
69 |
|
70 iPluginAdapter = aPluginAdapter; |
|
71 |
|
72 if ( aParentControl != NULL ) |
|
73 { |
|
74 CreateWindowL( aParentControl ); |
|
75 } |
|
76 else |
|
77 { |
|
78 CreateWindowL(); |
|
79 } |
|
80 ActivateL(); |
|
81 |
|
82 MakeVisible( ETrue ); // make it invisible for now |
|
83 |
|
84 DBG_TRACE_FN_END; |
|
85 } |
|
86 |
|
87 // --------------------------------------------------------------------------- |
|
88 // Constructor |
|
89 // --------------------------------------------------------------------------- |
|
90 // |
|
91 CGifAnimationPluginControl::CGifAnimationPluginControl() |
|
92 : iSourceImage( NULL ), |
|
93 iDrawingBitmap( NULL ), |
|
94 iScalingBitmap( NULL ), |
|
95 iScalingBitmapMask( NULL ), |
|
96 iEngine( NULL ), |
|
97 iAnimationState( EAnimationNotReady ), |
|
98 iLastError( KErrNone ) |
|
99 { |
|
100 DBG_TRACE_FN_BEGIN; |
|
101 // nothing goes here |
|
102 DBG_TRACE_FN_END; |
|
103 } |
|
104 |
|
105 // --------------------------------------------------------------------------- |
|
106 // Destructor. |
|
107 // --------------------------------------------------------------------------- |
|
108 // |
|
109 CGifAnimationPluginControl::~CGifAnimationPluginControl() |
|
110 { |
|
111 DBG_TRACE_FN_BEGIN; |
|
112 |
|
113 DeleteAnimation(); |
|
114 |
|
115 iPluginAdapter = NULL; |
|
116 |
|
117 DBG_TRACE_FN_END; |
|
118 } |
|
119 |
|
120 // --------------------------------------------------------- |
|
121 // Loads the image into display. |
|
122 // Param aImageFileName image file name - expected to be valid image |
|
123 // --------------------------------------------------------- |
|
124 // |
|
125 void CGifAnimationPluginControl::LoadImageL( const TDesC& aImageFileName ) |
|
126 { |
|
127 DBG_TRACE_FN_BEGIN; |
|
128 iFileName.Copy( aImageFileName ); |
|
129 |
|
130 iLastError = KErrNotReady; // if asked before loading is complete+Draw() |
|
131 TRAPD( error, DoImageLoadingL() ); |
|
132 if ( error ) |
|
133 { |
|
134 iLastError = error; |
|
135 DeleteAnimation(); |
|
136 DBG_TRACE_FN_END; |
|
137 User::Leave( error ); // re-throw it |
|
138 } |
|
139 else |
|
140 { |
|
141 DBG_TRACE( "Animation loaded" ); |
|
142 iAnimationState = EAnimationLoading; |
|
143 iLastError = KErrNone; |
|
144 } |
|
145 DBG_TRACE_FN_END; |
|
146 } |
|
147 |
|
148 // --------------------------------------------------------- |
|
149 // Return ETrue if loaded image is animation. |
|
150 // --------------------------------------------------------- |
|
151 // |
|
152 TBool CGifAnimationPluginControl::IsAnimation() const |
|
153 { |
|
154 DBG_TRACE_FN_BEGIN; |
|
155 if ( iSourceImage |
|
156 && iLastError == KErrNone ) // we did not have any error loading picture |
|
157 { |
|
158 DBG_TRACE_FN_END; |
|
159 return iSourceImage->IsAnimation(); |
|
160 } |
|
161 DBG_TRACE_FN_END; |
|
162 return EFalse; |
|
163 } |
|
164 |
|
165 |
|
166 // --------------------------------------------------------- |
|
167 // Return TInt with image loading error. |
|
168 // --------------------------------------------------------- |
|
169 // |
|
170 TBool CGifAnimationPluginControl::GetLastError() const |
|
171 { |
|
172 DBG_TRACE_FN_BEGIN; |
|
173 // |
|
174 DBG_TRACE_FN_END; |
|
175 return iLastError; |
|
176 } |
|
177 |
|
178 // --------------------------------------------------------- |
|
179 // Start animation. |
|
180 // --------------------------------------------------------- |
|
181 // |
|
182 void CGifAnimationPluginControl::StartAnimationL() |
|
183 { |
|
184 DBG_TRACE_FN_BEGIN; |
|
185 |
|
186 if ( iEngine == NULL ) // animation was stopped, |
|
187 { // need to re-load animation file |
|
188 DoImageLoadingL(); |
|
189 } |
|
190 |
|
191 // start animation |
|
192 if ( iEngine && IsAnimation() ) |
|
193 { |
|
194 iEngine->Play(); |
|
195 iAnimationState = EAnimationPlaying; |
|
196 } |
|
197 |
|
198 DBG_TRACE_FN_END; |
|
199 } |
|
200 |
|
201 // --------------------------------------------------------- |
|
202 // Stop animation. |
|
203 // --------------------------------------------------------- |
|
204 // |
|
205 void CGifAnimationPluginControl::StopAnimation() |
|
206 { |
|
207 DBG_TRACE_FN_BEGIN; |
|
208 |
|
209 // bugfix for JPYO-6KXHRW |
|
210 MakeVisible( EFalse ); |
|
211 |
|
212 |
|
213 // instead of just stopping player, we delete it. |
|
214 // This is because of stability issues with the start-stop-destroy cycle |
|
215 DeleteAnimation(); |
|
216 DBG_TRACE_FN_END; |
|
217 } |
|
218 |
|
219 // --------------------------------------------------------- |
|
220 // Called when size is changed. |
|
221 // --------------------------------------------------------- |
|
222 // |
|
223 void CGifAnimationPluginControl::SizeChanged() |
|
224 { |
|
225 DBG_TRACE_FN_BEGIN; |
|
226 if ( iEngine ) |
|
227 { |
|
228 iEngine->SetViewerSize( Size() ); |
|
229 } |
|
230 DBG_TRACE_FN_END; |
|
231 } |
|
232 |
|
233 // --------------------------------------------------------------------------- |
|
234 // Overriden CCoeControl::Draw() |
|
235 // --------------------------------------------------------------------------- |
|
236 // |
|
237 void CGifAnimationPluginControl::Draw( const TRect& /*aRect*/ ) const |
|
238 { |
|
239 //DBG_TRACE_FN_BEGIN; |
|
240 CWindowGc& gc = SystemGc(); |
|
241 TRect rect( Rect() ); |
|
242 |
|
243 DBG_TRACE( "Draw: Clearing background" ); |
|
244 gc.Clear( Rect() ); |
|
245 gc.SetBrushColor( KRgbBlack ); |
|
246 gc.SetBrushStyle( CGraphicsContext::ESolidBrush); |
|
247 gc.DrawRect( rect ); |
|
248 |
|
249 if ( iDrawingBitmap |
|
250 && iEngine |
|
251 && iLastError == KErrNone ) // loading was successful |
|
252 { |
|
253 TSize screenSize( rect.Size() ); |
|
254 TPoint destinationPoint( |
|
255 ( screenSize.iWidth-iTargetNewSize.iWidth ) / 2, |
|
256 ( screenSize.iHeight-iTargetNewSize.iHeight ) / 2 ); |
|
257 |
|
258 TSize drawingBitmapSize( iDrawingBitmap->Bitmap().SizeInPixels() ); |
|
259 if ( drawingBitmapSize.iHeight == iTargetNewSize.iHeight |
|
260 && drawingBitmapSize.iWidth == iTargetNewSize.iWidth ) |
|
261 { |
|
262 // we use unscaled version as size is Ok |
|
263 iDrawingBitmap->Draw( gc, |
|
264 destinationPoint, |
|
265 iTargetNewSize ); |
|
266 } |
|
267 else |
|
268 { |
|
269 // we use scaled version |
|
270 if ( iDrawingBitmap->HasMask() ) |
|
271 { |
|
272 gc.BitBltMasked( destinationPoint, |
|
273 iScalingBitmap, |
|
274 iTargetNewSize, |
|
275 iScalingBitmapMask, |
|
276 EFalse ); |
|
277 } |
|
278 else |
|
279 { |
|
280 gc.BitBlt( destinationPoint, |
|
281 iScalingBitmap ); |
|
282 } |
|
283 } |
|
284 } |
|
285 else // image is not ready or broken |
|
286 { |
|
287 DBG_TRACE( "image is not ready or broken" ); |
|
288 } |
|
289 //DBG_TRACE_FN_END; |
|
290 } |
|
291 |
|
292 // --------------------------------------------------------- |
|
293 // CGifAnimationPluginControl::DoImageLoadingL |
|
294 // --------------------------------------------------------- |
|
295 // |
|
296 void CGifAnimationPluginControl::DoImageLoadingL() |
|
297 { |
|
298 DBG_TRACE_FN_BEGIN; |
|
299 |
|
300 RFs& fs = CEikonEnv::Static()->FsSession(); |
|
301 TBool fileExists = BaflUtils::FileExists( fs, iFileName ); |
|
302 if ( !fileExists ) |
|
303 { |
|
304 DBG_TRACE_FN_END; |
|
305 User::Leave( KErrPathNotFound ); |
|
306 } |
|
307 |
|
308 |
|
309 RFile fileHandle; |
|
310 CleanupClosePushL( fileHandle ); |
|
311 iLastError = fileHandle.Open( fs, iFileName, EFileRead | EFileShareReadersOnly ); |
|
312 User::LeaveIfError(iLastError); |
|
313 |
|
314 // delete old instances, if any |
|
315 DeleteAnimation(); |
|
316 |
|
317 // create new objects |
|
318 if ( iDrawingBitmap == NULL ) |
|
319 { |
|
320 iDrawingBitmap = IHLBitmap::CreateL(); |
|
321 } |
|
322 |
|
323 TInt drmOption( 0 ); |
|
324 if ( isPreviewMode ) |
|
325 { |
|
326 drmOption = MIHLFileImage::EOptionNoDRMConsume; |
|
327 } |
|
328 iSourceImage = IHLImageFactory::OpenFileImageL( fileHandle, |
|
329 0, // image index |
|
330 drmOption ); |
|
331 |
|
332 // calculate target size so that picture fits the screen and centered |
|
333 TSize sourceSize( iSourceImage->Size() ); |
|
334 TSize maxSize = Size(); |
|
335 |
|
336 iTargetSize = TSize( Min( sourceSize.iWidth, maxSize.iWidth ), |
|
337 Min( sourceSize.iHeight, maxSize.iHeight ) ); |
|
338 |
|
339 if ( sourceSize.iWidth < maxSize.iWidth |
|
340 && sourceSize.iHeight < maxSize.iHeight ) |
|
341 { |
|
342 // scale up N-times |
|
343 TInt upScale = Min( maxSize.iWidth / sourceSize.iWidth, |
|
344 maxSize.iHeight / sourceSize.iHeight ); |
|
345 iTargetSize = TSize( sourceSize.iWidth * upScale, |
|
346 sourceSize.iHeight * upScale ); |
|
347 const TUint32 options( 0 ); // no flags set |
|
348 // we do not want IHL do scaling, so targetSize= sourceSize |
|
349 iEngine = IHLViewerFactory::CreateImageViewerL( sourceSize, |
|
350 *iSourceImage, |
|
351 *iDrawingBitmap, |
|
352 *this, |
|
353 options ); |
|
354 iTargetNewSize = iTargetSize; |
|
355 } |
|
356 else |
|
357 { |
|
358 //The image needs to be scaled down. We pass the target size to |
|
359 //IHL so that it doesn't come back with an OOM situation in case |
|
360 //the resolution is too high. |
|
361 // scale up N-times |
|
362 TReal downScale = Min( TReal(maxSize.iWidth) / TReal(sourceSize.iWidth), |
|
363 TReal(maxSize.iHeight) / TReal(sourceSize.iHeight) ); |
|
364 iTargetSize = TSize( sourceSize.iWidth * downScale, |
|
365 sourceSize.iHeight * downScale ); |
|
366 const TUint32 options( 0 ); // no flags set |
|
367 TReal widthRatio( TReal( iTargetSize.iWidth ) / TReal( sourceSize.iWidth ) ); |
|
368 TReal heightRatio( TReal( iTargetSize.iHeight ) / TReal( sourceSize.iHeight ) ); |
|
369 if( options & MIHLImageViewer::EOptionIgnoreAspectRatio ) |
|
370 { |
|
371 downScale = ( widthRatio > heightRatio ) ? widthRatio : heightRatio; |
|
372 } |
|
373 else |
|
374 { |
|
375 downScale = ( widthRatio < heightRatio ) ? widthRatio : heightRatio; |
|
376 } |
|
377 TReal widthZoomRatio( downScale ); |
|
378 TReal heightZoomRatio( downScale ); |
|
379 if( options & MIHLImageViewer::EOptionIgnoreAspectRatio ) |
|
380 { |
|
381 TReal widthRatio( TReal( iTargetSize.iWidth ) / TReal( sourceSize.iWidth ) ); |
|
382 TReal heightRatio( TReal( iTargetSize.iHeight ) / TReal( sourceSize.iHeight ) ); |
|
383 if( widthRatio < heightRatio ) |
|
384 { |
|
385 widthZoomRatio = widthZoomRatio * widthRatio / heightRatio; |
|
386 } |
|
387 else |
|
388 { |
|
389 heightZoomRatio = heightZoomRatio * heightRatio / widthRatio; |
|
390 } |
|
391 } |
|
392 iTargetNewSize = TSize( sourceSize.iWidth * widthZoomRatio, |
|
393 sourceSize.iHeight * heightZoomRatio ); |
|
394 // we do not want IHL do scaling, so targetSize= sourceSize |
|
395 iEngine = IHLViewerFactory::CreateImageViewerL( iTargetSize, |
|
396 *iSourceImage, |
|
397 *iDrawingBitmap, |
|
398 *this, |
|
399 options ); |
|
400 } |
|
401 |
|
402 // create bitmaps needed for manual scaling |
|
403 TDisplayMode dMode = CEikonEnv::Static()->DefaultDisplayMode(); |
|
404 if ( iScalingBitmap == NULL ) |
|
405 { |
|
406 iScalingBitmap = new( ELeave ) CFbsBitmap; |
|
407 iScalingBitmap->Create( iTargetSize, dMode ); |
|
408 } |
|
409 |
|
410 if ( iScalingBitmapMask == NULL ) |
|
411 { |
|
412 iScalingBitmapMask = new( ELeave ) CFbsBitmap; |
|
413 iScalingBitmapMask->Create( iTargetSize, dMode ); |
|
414 } |
|
415 |
|
416 CleanupStack::PopAndDestroy( &fileHandle ); |
|
417 DBG_TRACE_FN_END; |
|
418 } |
|
419 |
|
420 // --------------------------------------------------------- |
|
421 // CGifAnimationPluginControl::CheckFileIsValidL |
|
422 // --------------------------------------------------------- |
|
423 // |
|
424 void CGifAnimationPluginControl::CheckFileIsValidL( |
|
425 const TDesC& aImageFileName ) |
|
426 { |
|
427 DBG_TRACE_FN_BEGIN; |
|
428 |
|
429 ASSERT( aImageFileName.Size() ); |
|
430 CGifAnimationPluginControl* temp = |
|
431 new ( ELeave )CGifAnimationPluginControl(); |
|
432 CleanupStack::PushL( temp ); |
|
433 temp->SetSize( TSize( 100, 100 ) ); |
|
434 temp->SetPreviewMode(); |
|
435 temp->LoadImageL( aImageFileName ); |
|
436 temp->DeleteAnimation(); |
|
437 CleanupStack::PopAndDestroy( temp ); |
|
438 |
|
439 DBG_TRACE_FN_END; |
|
440 } |
|
441 |
|
442 // --------------------------------------------------------- |
|
443 // CGifAnimationPluginControl::DeleteAnimation |
|
444 // --------------------------------------------------------- |
|
445 // |
|
446 void CGifAnimationPluginControl::DeleteAnimation() |
|
447 { |
|
448 DBG_TRACE_FN_BEGIN; |
|
449 if ( iEngine ) |
|
450 { |
|
451 iAnimationState = EAnimationNotReady; |
|
452 iEngine->Stop(); |
|
453 delete iEngine; |
|
454 iEngine = NULL; |
|
455 } |
|
456 |
|
457 if ( iSourceImage ) |
|
458 { |
|
459 delete iSourceImage; |
|
460 iSourceImage = NULL; |
|
461 } |
|
462 |
|
463 if ( iDrawingBitmap ) |
|
464 { |
|
465 delete iDrawingBitmap; |
|
466 iDrawingBitmap = NULL; |
|
467 } |
|
468 |
|
469 if ( iScalingBitmap ) |
|
470 { |
|
471 delete iScalingBitmap; |
|
472 iScalingBitmap = NULL; |
|
473 } |
|
474 |
|
475 if ( iScalingBitmapMask ) |
|
476 { |
|
477 delete iScalingBitmapMask; |
|
478 iScalingBitmapMask = NULL; |
|
479 } |
|
480 |
|
481 |
|
482 DBG_TRACE_FN_END; |
|
483 } |
|
484 |
|
485 // --------------------------------------------------------- |
|
486 // Handle bitmap change notifications. State is changed accordingly |
|
487 // if this is the first frame. |
|
488 // --------------------------------------------------------- |
|
489 // |
|
490 void CGifAnimationPluginControl::ViewerBitmapChangedL() |
|
491 { |
|
492 switch ( iAnimationState ) |
|
493 { |
|
494 case EAnimationLoading: |
|
495 { |
|
496 iAnimationState = EAnimationPlaying; |
|
497 break; |
|
498 } |
|
499 case EAnimationPlaying: |
|
500 { |
|
501 // do nothing |
|
502 break; |
|
503 } |
|
504 case EAnimationNotReady: |
|
505 default: |
|
506 { |
|
507 break; |
|
508 } |
|
509 } |
|
510 |
|
511 if( iAnimationState == EAnimationPlaying ) |
|
512 { |
|
513 if ( iDrawingBitmap |
|
514 && iEngine |
|
515 && iLastError == KErrNone ) // loading was successful |
|
516 { |
|
517 TSize drawingBitmapSize( iDrawingBitmap->Bitmap().SizeInPixels() ); |
|
518 if ( drawingBitmapSize.iHeight == iTargetNewSize.iHeight |
|
519 && drawingBitmapSize.iWidth == iTargetNewSize.iWidth ) |
|
520 { |
|
521 // we do not need to do scaling |
|
522 } |
|
523 else |
|
524 { |
|
525 // we need to do scaling |
|
526 CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL( iScalingBitmap ); |
|
527 CleanupStack::PushL(bitmapDevice); |
|
528 CFbsBitGc* graphicsContext = NULL; |
|
529 User::LeaveIfError( bitmapDevice->CreateContext( graphicsContext ) ); |
|
530 CleanupStack::PushL( graphicsContext ); |
|
531 TRect srcRect( iSourceImage->Size() ); |
|
532 graphicsContext->DrawBitmap( iTargetSize, &iDrawingBitmap->Bitmap(), srcRect ); |
|
533 CleanupStack::PopAndDestroy( 2 );//graphicsContext,bitmapDevice |
|
534 |
|
535 if ( iDrawingBitmap->HasMask() ) |
|
536 { |
|
537 CFbsBitmapDevice* bitmapMaskDevice = CFbsBitmapDevice::NewL( iScalingBitmapMask ); |
|
538 CleanupStack::PushL(bitmapMaskDevice); |
|
539 CFbsBitGc* graphicsMaskContext = NULL; |
|
540 User::LeaveIfError( bitmapMaskDevice->CreateContext( graphicsMaskContext ) ); |
|
541 CleanupStack::PushL( graphicsMaskContext ); |
|
542 graphicsContext->DrawBitmap( iTargetSize, &iDrawingBitmap->Mask(), srcRect ); |
|
543 CleanupStack::PopAndDestroy( 2 );//graphicsContext,bitmapDevice |
|
544 } |
|
545 } |
|
546 } |
|
547 |
|
548 MakeVisible( ETrue ); |
|
549 DrawNow(); |
|
550 } |
|
551 } |
|
552 |
|
553 // --------------------------------------------------------- |
|
554 // Handles engine errors. |
|
555 // --------------------------------------------------------- |
|
556 // |
|
557 void CGifAnimationPluginControl::ViewerError( TInt aError ) |
|
558 { |
|
559 DBG_TRACE_FN_BEGIN; |
|
560 iLastError = aError; |
|
561 HandleCallback( aError ); |
|
562 DBG_TRACE_FN_END; |
|
563 } |
|
564 |
|
565 |
|
566 // --------------------------------------------------------- |
|
567 // Handles error codes; stores the error |
|
568 // --------------------------------------------------------- |
|
569 // |
|
570 void CGifAnimationPluginControl::HandleCallback( TInt aError ) |
|
571 { |
|
572 DBG_TRACE_FN_BEGIN; |
|
573 |
|
574 if ( aError ) |
|
575 { |
|
576 InformPluginFinished(); |
|
577 } |
|
578 |
|
579 DBG_TRACE_FN_END; |
|
580 } |
|
581 |
|
582 |
|
583 // --------------------------------------------------------- |
|
584 // Informs that plug-in wants to terminate |
|
585 // --------------------------------------------------------- |
|
586 // |
|
587 void CGifAnimationPluginControl::InformPluginFinished() |
|
588 { |
|
589 |
|
590 ASSERT( iPluginAdapter ); |
|
591 |
|
592 StopAnimation(); |
|
593 |
|
594 TRAP_IGNORE(iPluginAdapter->PluginFinishedL()); |
|
595 } |
|
596 |
|
597 void CGifAnimationPluginControl::SetPreviewMode() |
|
598 { |
|
599 isPreviewMode = ETrue; |
|
600 } |
|