messagingappbase/msgeditor/mediacontrolsrc/MsgImageControl.cpp
changeset 79 2981cb3aa489
equal deleted inserted replaced
25:84d9eb65b26f 79:2981cb3aa489
       
     1 /*
       
     2 * Copyright (c) 2005-2006 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 *       MsgEditor image UI control - a Message Editor Base control.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include "MsgImageControl.h"
       
    23 
       
    24 #include <DRMCommon.h>
       
    25 #include <AknUtils.h>               // AknsUtils
       
    26 #include <AknsDrawUtils.h>          // AknsDrawUtils
       
    27 #include <aknlayoutscalable_apps.cdl.h>
       
    28 
       
    29 #include <MsgEditorView.h>          // CMsgEditorView
       
    30 #include <MsgEditorCommon.h>
       
    31 
       
    32 #include <IHLImageFactory.h>        // IHLImageFactory
       
    33 #include <IHLViewerFactory.h>       // IHLViewerFactory
       
    34 #include <MIHLFileImage.h>          // MIHLFileImage
       
    35 #include <MIHLBitmap.h>             // MIHLBitmap
       
    36 #include <MIHLImageViewer.h>        // MIHLImageViewer
       
    37 #include <icl/imagecodecdata.h>     // KImageTypeBMPUid
       
    38 
       
    39 #include "MsgFrameControl.h"
       
    40 #include "MsgIconControl.h"
       
    41 #include "MsgBitmapControl.h"
       
    42 
       
    43 #include "MsgMediaControlLogging.h"
       
    44 
       
    45 // ==========================================================
       
    46 
       
    47 // EXTERNAL DATA STRUCTURES
       
    48 
       
    49 // EXTERNAL FUNCTION PROTOTYPES
       
    50 
       
    51 // CONSTANTS
       
    52 
       
    53 // MACROS
       
    54 
       
    55 // LOCAL CONSTANTS AND MACROS
       
    56 const TInt KAnimationStartDelay = 500000; // 0,5s
       
    57 const TInt KAnimationDelayBetweenLoops = 1000000; // 1s
       
    58 
       
    59 // MODULE DATA STRUCTURES
       
    60 
       
    61 // LOCAL FUNCTION PROTOTYPES
       
    62 
       
    63 // ================= MEMBER FUNCTIONS =======================
       
    64 
       
    65 // ---------------------------------------------------------
       
    66 // CMsgImageControl::CMsgImageControl
       
    67 //
       
    68 // Constructor.
       
    69 // ---------------------------------------------------------
       
    70 //
       
    71 CMsgImageControl::CMsgImageControl( MMsgBaseControlObserver& aBaseControlObserver ) : 
       
    72     CMsgMediaControl( aBaseControlObserver, EMsgComponentIdImage, EMsgImageControl )
       
    73     {
       
    74     }
       
    75 
       
    76 // ---------------------------------------------------------
       
    77 // CMsgImageControl::ConstructL
       
    78 // ---------------------------------------------------------
       
    79 //
       
    80 void CMsgImageControl::ConstructL( CMsgEditorView& aParent, MMsgAsyncControlObserver* aObserver )
       
    81     {
       
    82     BaseConstructL( aParent, aObserver );    
       
    83     
       
    84     iBitmapControl = new( ELeave ) CMsgBitmapControl;
       
    85     iBitmapControl->SetContainerWindowL( *this );
       
    86     
       
    87     CalculateMaxSize();
       
    88 
       
    89     TRect rect( aParent.Rect() );
       
    90     if ( rect.Height() == 0 || rect.Width() == 0 )
       
    91         {
       
    92         // We have been called before view construction.
       
    93         // Set rect to screen size.
       
    94         rect.SetRect( TPoint(), iMaxSize );
       
    95         }
       
    96 
       
    97     SetRect( rect );
       
    98     
       
    99     iLoopTimer = CPeriodic::NewL( EPriorityNormal );
       
   100     }
       
   101 
       
   102 // ---------------------------------------------------------
       
   103 // CMsgImageControl::NewL
       
   104 //
       
   105 // Two-phased constructor.
       
   106 // ---------------------------------------------------------
       
   107 //
       
   108 EXPORT_C CMsgImageControl* CMsgImageControl::NewL( CMsgEditorView& aParent,
       
   109                                                    MMsgAsyncControlObserver* aObserver )
       
   110     {
       
   111     CMsgImageControl* self = new( ELeave ) CMsgImageControl( aParent );
       
   112     
       
   113     CleanupStack::PushL( self );
       
   114     self->ConstructL( aParent, aObserver );
       
   115     CleanupStack::Pop( self );
       
   116     
       
   117     return self;
       
   118     }
       
   119 
       
   120 // ---------------------------------------------------------
       
   121 // CMsgImageControl::~CMsgImageControl
       
   122 //
       
   123 // Destructor
       
   124 // ---------------------------------------------------------
       
   125 //
       
   126 CMsgImageControl::~CMsgImageControl()
       
   127     {
       
   128     delete iEngine;
       
   129     delete iDestinationBitmap;
       
   130     delete iSourceImage;
       
   131     delete iBitmapControl;
       
   132     delete iLoopTimer;
       
   133     }
       
   134     
       
   135 // ---------------------------------------------------------
       
   136 // CMsgImageControl::LoadL
       
   137 // ---------------------------------------------------------
       
   138 //
       
   139 void CMsgImageControl::LoadL( RFile& aFileHandle )
       
   140     {
       
   141     Reset();
       
   142     
       
   143     iSourceImage = IHLImageFactory::OpenFileImageL( aFileHandle, 
       
   144                                                     0,  // image index
       
   145                                                     MIHLFileImage::EOptionNoDRMConsume );
       
   146     
       
   147     SetState( EMsgAsyncControlStateOpening );
       
   148     
       
   149     iDestinationBitmap = IHLBitmap::CreateL();
       
   150             
       
   151     TSize sourceSize( iSourceImage->Size() );
       
   152     TSize targetSize = TSize(
       
   153     Min( sourceSize.iWidth, iMaxSize.iWidth - iFrame->FrameBorderSize().iWidth ),
       
   154     Min( sourceSize.iHeight, iMaxSize.iHeight - iFrame->FrameBorderSize().iHeight ) );
       
   155 
       
   156     // Avoiding the usage of MIHLImageViewer::EOptionUseBilinearInterpolation
       
   157     // because it should be only used for small images because of the memory requirements
       
   158     // and it is much slower than the regular scaling
       
   159     //For any type of image, nearest neighbour method(default) will be used to resize it. 
       
   160     
       
   161     iEngine = IHLViewerFactory::CreateImageViewerL( targetSize,
       
   162                                                     *iSourceImage, 
       
   163                                                     *iDestinationBitmap, 
       
   164                                                     *this);                        	
       
   165     }
       
   166 
       
   167 // ---------------------------------------------------------
       
   168 // CMsgImageControl::Cancel
       
   169 // ---------------------------------------------------------
       
   170 //
       
   171 void CMsgImageControl::Cancel()
       
   172     {
       
   173     if ( iState == EMsgAsyncControlStateOpening )
       
   174         {
       
   175         Reset();
       
   176         
       
   177         SetState( EMsgAsyncControlStateIdle );
       
   178         }
       
   179     }
       
   180 
       
   181 // ---------------------------------------------------------
       
   182 // CMsgImageControl::PlayL
       
   183 // ---------------------------------------------------------
       
   184 //
       
   185 void CMsgImageControl::PlayL()
       
   186     {
       
   187     if ( IsAnimation() &&
       
   188          iState >= EMsgAsyncControlStateOpening )
       
   189         {
       
   190         DoPlay( 0 );
       
   191         }
       
   192     }
       
   193 
       
   194 // ---------------------------------------------------------
       
   195 // CMsgImageControl::PauseL
       
   196 // ---------------------------------------------------------
       
   197 //
       
   198 void CMsgImageControl::PauseL()
       
   199     {
       
   200     if ( IsAnimation() && 
       
   201          iState >= EMsgAsyncControlStateReady )
       
   202         {
       
   203         DoPause();
       
   204         }
       
   205     }
       
   206      
       
   207 // ---------------------------------------------------------
       
   208 // CMsgImageControl::Stop
       
   209 // ---------------------------------------------------------
       
   210 //
       
   211 void CMsgImageControl::Stop()
       
   212     {    
       
   213     if ( IsAnimation() && 
       
   214          iState >= EMsgAsyncControlStateReady )
       
   215         {
       
   216         StopAnimation();
       
   217     
       
   218         SetState( EMsgAsyncControlStateStopped );
       
   219         }
       
   220     }
       
   221 
       
   222 // ---------------------------------------------------------
       
   223 // CMsgImageControl::Close
       
   224 // ---------------------------------------------------------
       
   225 //
       
   226 void CMsgImageControl::Close()
       
   227     {
       
   228     Stop();
       
   229     SetState( EMsgAsyncControlStateIdle );
       
   230     }
       
   231 
       
   232 // ---------------------------------------------------------
       
   233 // CMsgImageControl::IsAnimation
       
   234 //
       
   235 // Return ETrue if loaded image is animation.
       
   236 // ---------------------------------------------------------
       
   237 //
       
   238 EXPORT_C TBool CMsgImageControl::IsAnimation() const
       
   239     {
       
   240     TBool result( EFalse );
       
   241     
       
   242     if ( iSourceImage )
       
   243         {
       
   244         result = iSourceImage->IsAnimation();
       
   245         }
       
   246         
       
   247     return result;
       
   248     }
       
   249 
       
   250 // ---------------------------------------------------------
       
   251 // CMsgImageControl::SetAnimationLoopCount
       
   252 //
       
   253 // Sets animation loop count (i.e. how many times animation
       
   254 // is played fully through). -1 means that it is looped forever.
       
   255 // ---------------------------------------------------------
       
   256 //
       
   257 EXPORT_C void CMsgImageControl::SetAnimationLoopCount( TInt aCount )
       
   258     {
       
   259     iLoopCount = aCount;
       
   260     }
       
   261 
       
   262 // ---------------------------------------------------------
       
   263 // CMsgImageControl::SetImageFileOpenOrClose
       
   264 //
       
   265 // Sets image file open or close.
       
   266 // ---------------------------------------------------------
       
   267 //
       
   268 EXPORT_C void CMsgImageControl::SetImageFileClosed( )
       
   269     {
       
   270     if ( iSourceImage )
       
   271         {
       
   272         Stop();
       
   273         
       
   274         delete iSourceImage;
       
   275         iSourceImage = NULL;
       
   276         
       
   277         delete iEngine;
       
   278         iEngine = NULL;
       
   279         
       
   280         SetState( EMsgAsyncControlStateIdle );
       
   281         }
       
   282     }
       
   283 
       
   284 // ---------------------------------------------------------
       
   285 // CMsgImageControl::SetAndGetSizeL
       
   286 //
       
   287 // Calculates and sets the size of the control and returns new size as
       
   288 // reference aSize.
       
   289 // ---------------------------------------------------------
       
   290 //
       
   291 void CMsgImageControl::SetAndGetSizeL( TSize& aSize )
       
   292     {
       
   293     // Adjust max height if needed
       
   294     if ( aSize.iHeight > iMaxSize.iHeight )
       
   295         {
       
   296         aSize.iHeight = iMaxSize.iHeight;
       
   297         }
       
   298 
       
   299     // Do not adjust the width. The width of the control must always
       
   300     // be the same as the width of the client rect.
       
   301     aSize = CalculateControlSize( aSize );
       
   302 
       
   303     SetSize( aSize );
       
   304     }
       
   305 
       
   306 
       
   307 // ---------------------------------------------------------
       
   308 // CMsgImageControl::NotifyViewEvent
       
   309 //
       
   310 // Animation playback is paused if view looses focus and resumed
       
   311 // when focus is again gained. Resuming happens only if animation is
       
   312 // still at pause state and control is on playing state.
       
   313 // ---------------------------------------------------------
       
   314 //
       
   315 void CMsgImageControl::NotifyViewEvent( TMsgViewEvent aEvent, TInt aParam )
       
   316     {
       
   317     switch ( aEvent )
       
   318         {
       
   319         case EMsgViewEventViewFocusLost:
       
   320             {
       
   321             if ( iAnimationState == EAnimationPlaying )
       
   322                 {
       
   323                 PauseAnimation();
       
   324                 }
       
   325             break;
       
   326             }
       
   327         case EMsgViewEventViewFocusGain:
       
   328             {
       
   329             if ( iAnimationState == EAnimationPaused &&
       
   330                  iState == EMsgAsyncControlStatePlaying )
       
   331                 {
       
   332                 StartAnimation( KAnimationStartDelay );
       
   333                 }
       
   334             break;
       
   335             }
       
   336         default:
       
   337             {
       
   338             break;
       
   339             }
       
   340         }
       
   341         
       
   342     CMsgMediaControl::NotifyViewEvent( aEvent, aParam );
       
   343     }
       
   344 
       
   345 // ---------------------------------------------------------
       
   346 // CMsgImageControl::Reset
       
   347 //
       
   348 // Empties the control.
       
   349 // ---------------------------------------------------------
       
   350 //
       
   351 void CMsgImageControl::Reset()
       
   352     {
       
   353     delete iEngine;
       
   354     iEngine = NULL;
       
   355     
       
   356     iAnimationState = EAnimationStopped;
       
   357     
       
   358     delete iDestinationBitmap;
       
   359     iDestinationBitmap = NULL;
       
   360     
       
   361     iBitmapControl->SetBitmap( NULL );
       
   362     
       
   363     delete iSourceImage;
       
   364     iSourceImage = NULL;
       
   365     
       
   366     ResetIconId();
       
   367     }
       
   368 
       
   369 // ---------------------------------------------------------
       
   370 // CMsgImageControl::FocusChanged
       
   371 //
       
   372 // Updates the focus (i.e. set frame control visible/invisible).
       
   373 // Calls base class implementation if icon is visible. Otherwise
       
   374 // performs it's own handling.
       
   375 // Frame control is redraw immediatelly if that 
       
   376 // is requested and frame control state is changed. Otherwise
       
   377 // normal deferred drawing is done. This is activated at 
       
   378 // CCoeControl::MakeVisible if needed.
       
   379 // ---------------------------------------------------------
       
   380 //
       
   381 void CMsgImageControl::FocusChanged( TDrawNow aDrawNow )
       
   382     {
       
   383     if ( VisiblePlaceholder() )
       
   384         {
       
   385         CMsgMediaControl::FocusChanged( aDrawNow );
       
   386         }
       
   387     else 
       
   388         {
       
   389         TBool oldVisibility( iFrame->IsVisible() );
       
   390     
       
   391         iFrame->MakeVisible( IsFocused() );
       
   392         
       
   393         if ( aDrawNow == EDrawNow &&
       
   394              iFrame->IsVisible() != oldVisibility )
       
   395             {
       
   396             DrawNow();
       
   397             }
       
   398         }
       
   399     }
       
   400 
       
   401 // ---------------------------------------------------------
       
   402 // CMsgImageControl::SizeChanged
       
   403 //
       
   404 // Called when size is changed.
       
   405 // ---------------------------------------------------------
       
   406 //
       
   407 void CMsgImageControl::SizeChanged()
       
   408     {
       
   409     if ( iEngine && 
       
   410          Size() != iEngine->ViewerSize() )
       
   411         {
       
   412         TSize bitmapSize = iEngine->SourceSize() ;
       
   413         TSize controlSize = iSize;
       
   414         controlSize.iWidth -= iFrame->FrameBorderSize().iWidth;
       
   415         controlSize.iHeight -= iFrame->FrameBorderSize().iHeight;
       
   416         
       
   417         TReal widthRatio = static_cast<TReal>( controlSize.iWidth ) / 
       
   418                            static_cast<TReal>( bitmapSize.iWidth );
       
   419         TReal heightRatio = static_cast<TReal>( controlSize.iHeight ) / 
       
   420                             static_cast<TReal>( bitmapSize.iHeight );
       
   421         TReal zoomRatio = ( widthRatio < heightRatio ) ? widthRatio : heightRatio;
       
   422         
       
   423         iEngine->SetViewerSize( Size() );
       
   424         iEngine->SetZoomRatio( zoomRatio );
       
   425         }
       
   426     
       
   427     // Size updated at the ViewerBitmapChanged when image scaling is done.
       
   428     iBitmapControl->SetPosition( Position() + CalculateImagePosition() );
       
   429         
       
   430     if ( iDestinationBitmap && 
       
   431          iDestinationBitmap->IsCreated() )
       
   432         {
       
   433         iFrame->SetImageSize( iDestinationBitmap->Bitmap().SizeInPixels() );
       
   434         }
       
   435     
       
   436     if ( iState == EMsgAsyncControlStatePlaying )
       
   437         {
       
   438         // Start animation if needed on playing state.
       
   439         StartAnimation( 0 );
       
   440         }
       
   441         
       
   442     CMsgMediaControl::SizeChanged();
       
   443     }
       
   444 
       
   445 // ---------------------------------------------------------
       
   446 // CMsgImageControl::Draw
       
   447 //
       
   448 // Draws the basic skin background for given rectangle. 
       
   449 // Image is drawn on CBitmapControl::Draw function.
       
   450 // ---------------------------------------------------------
       
   451 //
       
   452 void CMsgImageControl::Draw( const TRect& aRect ) const
       
   453     {
       
   454     CWindowGc& gc = SystemGc();
       
   455     
       
   456     if ( !VisiblePlaceholder() )
       
   457         {
       
   458         if ( !AknsDrawUtils::BackgroundBetweenRects( AknsUtils::SkinInstance(), 
       
   459                                                  AknsDrawUtils::ControlContext( this ), 
       
   460                                                  this, 
       
   461                                                  gc, 
       
   462                                                  Rect(),
       
   463                                                  iBitmapControl->Rect(),
       
   464                                                  KAknsDrawParamNoClearUnderImage ) )
       
   465             {
       
   466             gc.SetBrushColor( AKN_LAF_COLOR( 0 ) );
       
   467             gc.SetPenStyle( CGraphicsContext::ENullPen );
       
   468     		gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   469         	gc.DrawRect( aRect );
       
   470             }
       
   471         }
       
   472     else 
       
   473         {
       
   474         // Basic icon drawing from base class when icon is visible.
       
   475         CMsgMediaControl::Draw( aRect );
       
   476         }
       
   477     }
       
   478 
       
   479 // ---------------------------------------------------------
       
   480 // CMmsImageControl::MakeVisible
       
   481 //
       
   482 // Sets same visibility to bitmap control as image control has.
       
   483 // ---------------------------------------------------------
       
   484 //
       
   485 void CMsgImageControl::MakeVisible( TBool aVisible )
       
   486     {
       
   487     iBitmapControl->MakeVisible( aVisible );
       
   488     
       
   489     CMsgMediaControl::MakeVisible( aVisible );
       
   490     }
       
   491 
       
   492 // ---------------------------------------------------------
       
   493 // CMmsImageControl::PositionChanged
       
   494 //
       
   495 // Calculates new position to bitmap control as image control position
       
   496 // has changed.
       
   497 // ---------------------------------------------------------
       
   498 //
       
   499 void CMsgImageControl::PositionChanged()
       
   500     {
       
   501     iBitmapControl->SetPosition( Position() + CalculateImagePosition() );
       
   502     
       
   503     CMsgMediaControl::PositionChanged();
       
   504     }
       
   505 
       
   506 // ---------------------------------------------------------
       
   507 // CMsgImageControl::HandleResourceChange
       
   508 // ---------------------------------------------------------
       
   509 //
       
   510 void CMsgImageControl::HandleResourceChange( TInt aType )
       
   511     {
       
   512     CMsgMediaControl::HandleResourceChange( aType ); 
       
   513     
       
   514     if ( aType == KEikDynamicLayoutVariantSwitch )
       
   515         {
       
   516         CalculateMaxSize();
       
   517         
       
   518         if ( iEngine )
       
   519             {
       
   520             TSize sourceSize( iSourceImage->Size() );
       
   521             TSize targetSize = TSize(
       
   522                     Min( sourceSize.iWidth, iMaxSize.iWidth - iFrame->FrameBorderSize().iWidth ),
       
   523                     Min( sourceSize.iHeight, iMaxSize.iHeight - iFrame->FrameBorderSize().iHeight ) );
       
   524             
       
   525             iBitmapControl->SetSize( TSize( 0, 0 ) );
       
   526             SetSize( targetSize );
       
   527             }
       
   528         }
       
   529     }
       
   530 
       
   531 // ---------------------------------------------------------
       
   532 // CMmsImageControl::CountComponentControls
       
   533 //
       
   534 // Return count of controls be included in this component.
       
   535 // ---------------------------------------------------------
       
   536 //
       
   537 TInt CMsgImageControl::CountComponentControls() const
       
   538     {    
       
   539     return 2;
       
   540     }
       
   541 
       
   542 // ---------------------------------------------------------
       
   543 // CMmsImageControl::ComponentControl
       
   544 //
       
   545 // Return pointer to component in question.
       
   546 // Note! Image and Icon cannot exist at a same time.
       
   547 // ---------------------------------------------------------
       
   548 //
       
   549 CCoeControl* CMsgImageControl::ComponentControl( TInt aIndex ) const
       
   550     {
       
   551     CCoeControl* result = NULL;
       
   552     switch ( aIndex )
       
   553         {
       
   554         case 0:
       
   555             {
       
   556             result = iFrame;                
       
   557             break;
       
   558             }
       
   559         case 1:
       
   560             {
       
   561             CCoeControl* visiblePlaceholder = VisiblePlaceholder();
       
   562             if ( visiblePlaceholder )
       
   563                 {
       
   564                 result = visiblePlaceholder;
       
   565                 }
       
   566             else
       
   567                 {
       
   568                 result = iBitmapControl;
       
   569                 }
       
   570             break;
       
   571             }
       
   572         default:
       
   573             {
       
   574             break;
       
   575             }
       
   576         }
       
   577         
       
   578     return result;
       
   579     }
       
   580 
       
   581 // ---------------------------------------------------------
       
   582 // CMsgImageControl::IsOffScreen
       
   583 //
       
   584 // Returns ETrue if image is off screen.
       
   585 // ---------------------------------------------------------
       
   586 //
       
   587 TBool CMsgImageControl::IsOffScreen() const
       
   588     {
       
   589     TRect rect( Position() + CalculateImagePosition(),
       
   590                 iDestinationBitmap->Bitmap().SizeInPixels() );
       
   591     
       
   592     TBool result( EFalse );
       
   593     
       
   594     if ( rect.iTl.iY < 0 || 
       
   595          rect.iBr.iY >  MsgEditorCommons::MsgMainPane().Height() )
       
   596         {
       
   597         result = ETrue;
       
   598         }
       
   599         
       
   600     return result;
       
   601     }
       
   602 
       
   603 
       
   604 // ---------------------------------------------------------
       
   605 // CMsgImageControl::ViewerBitmapChangedL
       
   606 //
       
   607 // Handle bitmap change notifications. State is changed accordingly
       
   608 // if this is the first frame. GIF animation is stopped if control
       
   609 // goes off screen and started again when it is fully visible and control
       
   610 // is on playing state. On editor mode animation is looped only once. 
       
   611 // Animation is also stopped if animation loop count is reached.
       
   612 // New animation loop is started after KAnimationDelayBetweenLoops
       
   613 // delay.
       
   614 // ---------------------------------------------------------
       
   615 //
       
   616 void CMsgImageControl::ViewerBitmapChangedL()
       
   617     {
       
   618     if ( iState == EMsgAsyncControlStateOpening )   
       
   619         {
       
   620         SetState( EMsgAsyncControlStateReady );        
       
   621         
       
   622         if ( iAnimationState == EAnimationPlaying )
       
   623             {
       
   624             SetState( EMsgAsyncControlStatePlaying );
       
   625             }
       
   626         }
       
   627         
       
   628     if ( iSourceImage->IsAnimation() )
       
   629         {
       
   630         switch ( iAnimationState )
       
   631             {
       
   632             case EAnimationPlaying:
       
   633                 {   
       
   634                 if ( IsOffScreen() )
       
   635                     {
       
   636                     // Stop the playback if animation is not fully visible
       
   637                     StopAnimation();
       
   638                     }
       
   639                 else if ( iEngine->AnimationFrame() == 
       
   640                           iSourceImage->AnimationFrameCount() - 1 )
       
   641                     {
       
   642                     // Last frame of the animation has been loaded.
       
   643                     iCurrentLoop++;
       
   644                     
       
   645                     if ( iCurrentLoop == iLoopCount )
       
   646                         {
       
   647                         // Maximum loop count reached. Do not stop yet as first
       
   648                         // frame is wanted to be displayed. Stopping is done on 
       
   649                         // EAnimationStopped state.
       
   650                         iAnimationState = EAnimationStopped;
       
   651                         }
       
   652                     else
       
   653                         {
       
   654                         iEngine->Stop();
       
   655                         
       
   656                         iLoopTimer->Cancel();
       
   657                         iLoopTimer->Start( KAnimationDelayBetweenLoops,
       
   658                                            KAnimationDelayBetweenLoops,
       
   659                                            TCallBack( DoStartLoop, this ) );
       
   660                         }
       
   661                     }
       
   662                 break;
       
   663                 }
       
   664             case EAnimationStopped:
       
   665                 {
       
   666                 if( iState == EMsgAsyncControlStatePlaying &&
       
   667                     !IsOffScreen() &&
       
   668                     iCurrentLoop != iLoopCount )
       
   669                     {
       
   670                     StartAnimation( 0 );
       
   671                     }
       
   672                 else
       
   673                     {
       
   674                     StopAnimation();
       
   675                     }
       
   676                 break;
       
   677                 }
       
   678             case EAnimationNotReady:
       
   679             default:
       
   680                 {
       
   681                 break;
       
   682                 }
       
   683             }
       
   684         }
       
   685     
       
   686     iBitmapControl->SetBitmap( iDestinationBitmap );
       
   687     
       
   688     TRect imageRect( Position() + CalculateImagePosition(),
       
   689                      iDestinationBitmap->Bitmap().SizeInPixels() );
       
   690     iBitmapControl->SetRect( imageRect );
       
   691     
       
   692     if( IsVisible() )
       
   693         {
       
   694         // Sometimes iDestinationBitmap is not ready when in SizeChanged()
       
   695         if ( iDestinationBitmap &&  
       
   696              iDestinationBitmap->IsCreated() )
       
   697             {
       
   698             iFrame->SetImageSize( imageRect.Size() );
       
   699             }  
       
   700 
       
   701         DrawNow();
       
   702         }
       
   703     }
       
   704 
       
   705 // ---------------------------------------------------------
       
   706 // CMsgImageControl::ViewerError
       
   707 //
       
   708 // Handles engine errors.
       
   709 // ---------------------------------------------------------
       
   710 //
       
   711 void CMsgImageControl::ViewerError( TInt aError )
       
   712     {
       
   713     MSGMEDIACONTROLLOGGER_WRITEF_ERROR_STATE( _L("CMsgImageControl::HandleCallback: **aError: %d, CurrentState: %S"),aError, iState);
       
   714     
       
   715     iError = aError;
       
   716             
       
   717     switch ( aError )
       
   718         {
       
   719         case KErrNone:
       
   720             {
       
   721             if ( iState == EMsgAsyncControlStateOpening )
       
   722                 {
       
   723                 // image shown in the viewer and image had rights
       
   724                 SetState( EMsgAsyncControlStateReady );
       
   725                 DoPlay( 0 );
       
   726                 }
       
   727             else if (  iState == EMsgAsyncControlStatePlaying )
       
   728                 {
       
   729                 SetState( EMsgAsyncControlStateReady );
       
   730                 DoPlay( 0 );
       
   731                 }
       
   732             break;
       
   733             }
       
   734         case DRMCommon::EGeneralError:
       
   735         case DRMCommon::EUnknownMIME:
       
   736         case DRMCommon::EVersionNotSupported:
       
   737         case DRMCommon::ESessionError:
       
   738         case DRMCommon::ENoRights:
       
   739         case DRMCommon::ERightsDBCorrupted:
       
   740         case DRMCommon::EUnsupported:
       
   741         case DRMCommon::ERightsExpired:
       
   742         case DRMCommon::EInvalidRights:
       
   743             {
       
   744             SetState( EMsgAsyncControlStateNoRights );
       
   745             break;
       
   746             }
       
   747         case KErrNoMemory:  // cannot recover
       
   748         default:
       
   749             {
       
   750             SetState( EMsgAsyncControlStateCorrupt );
       
   751             break;
       
   752             }
       
   753         }
       
   754     }
       
   755 
       
   756 // ---------------------------------------------------------
       
   757 // CMsgImageControl::CalculateImagePosition
       
   758 //
       
   759 // Calculates image position so that it is centered to 
       
   760 // control extent.
       
   761 // ---------------------------------------------------------
       
   762 //
       
   763 TPoint CMsgImageControl::CalculateImagePosition() const
       
   764     {
       
   765     TPoint result;
       
   766     
       
   767     TSize controlSize( Size() );
       
   768     TSize imageSize;
       
   769     
       
   770     if ( iEngine )
       
   771         {
       
   772         imageSize = iEngine->SourceSize();
       
   773         imageSize.iWidth *= iEngine->ZoomRatio();
       
   774         imageSize.iHeight *= iEngine->ZoomRatio();
       
   775         }
       
   776     else
       
   777         {
       
   778         // Engine has been unloaded. Use current bitmap control size
       
   779         // as imageSize.
       
   780         imageSize = iBitmapControl->Size();
       
   781         }
       
   782     
       
   783     result.iX = ( controlSize.iWidth - imageSize.iWidth ) / 2;
       
   784     result.iY = ( controlSize.iHeight - imageSize.iHeight ) / 2;
       
   785     
       
   786     if ( result.iX < 0 )
       
   787         {
       
   788         result.iX = 0;
       
   789         }
       
   790     
       
   791     if ( result.iY < 0 )
       
   792         {
       
   793         result.iY = 0;
       
   794         }
       
   795         
       
   796     return result;
       
   797     }
       
   798 
       
   799 // ---------------------------------------------------------
       
   800 // CMsgImageControl::CalculateControlSize
       
   801 //
       
   802 // Calculates the correct size for the image control.
       
   803 // ---------------------------------------------------------
       
   804 //
       
   805 TSize CMsgImageControl::CalculateControlSize( const TSize& aProposedSize ) const
       
   806     {
       
   807     TSize result( aProposedSize.iWidth, 0 );
       
   808     TSize bitmapSize = BitmapSize();
       
   809     
       
   810     if ( !bitmapSize.iHeight || !bitmapSize.iWidth )
       
   811         {
       
   812         result.iHeight = aProposedSize.iHeight;
       
   813         return result;
       
   814         }
       
   815     else if ( bitmapSize.iHeight < aProposedSize.iHeight )
       
   816         {
       
   817         result.iHeight = bitmapSize.iHeight;
       
   818         }
       
   819     else
       
   820         {
       
   821         result.iHeight = aProposedSize.iHeight;
       
   822         }
       
   823 
       
   824     TInt scaledHeight( 
       
   825         ( static_cast<TReal>( bitmapSize.iHeight ) /
       
   826           static_cast<TReal>( bitmapSize.iWidth ) ) *
       
   827           aProposedSize.iWidth );
       
   828     if ( scaledHeight < result.iHeight )
       
   829         {
       
   830         result.iHeight = scaledHeight;
       
   831         }
       
   832 
       
   833     // Height should be multiple of baseline.
       
   834     // Round up to the next full multiple if needed.
       
   835     TInt remainder = result.iHeight % iBaseLine;
       
   836     if ( remainder )
       
   837         {
       
   838         result.iHeight += ( iBaseLine - remainder );
       
   839         }
       
   840         
       
   841     if ( result.iHeight > iMaxSize.iHeight )
       
   842         {
       
   843         result.iHeight = iMaxSize.iHeight;
       
   844         }
       
   845 
       
   846     return result;
       
   847     }
       
   848 
       
   849 // ---------------------------------------------------------
       
   850 // CMsgImageControl::BitmapSize
       
   851 // 
       
   852 // Returns correct size for bitmap.
       
   853 // ---------------------------------------------------------
       
   854 //
       
   855 TSize CMsgImageControl::BitmapSize() const
       
   856     {
       
   857     TSize bitmapSize( 0, 0 );
       
   858     if ( !iIconControl->IsVisible() &&
       
   859          ( iBitmapControl->Size().iWidth == 0 ||
       
   860            iBitmapControl->Size().iHeight == 0 ) )
       
   861         {
       
   862         if ( iEngine )
       
   863             {
       
   864             bitmapSize = iEngine->SourceSize() ;
       
   865             bitmapSize.iWidth += iFrame->FrameBorderSize().iWidth;
       
   866             bitmapSize.iHeight += iFrame->FrameBorderSize().iHeight;
       
   867             }
       
   868         }
       
   869     else 
       
   870         {
       
   871         // Bitmap or icon visible. 
       
   872         bitmapSize = iFrame->FrameSize();
       
   873         }
       
   874 
       
   875     return bitmapSize;
       
   876     }
       
   877 
       
   878 // ---------------------------------------------------------
       
   879 // CMsgImageControl::DoPlay
       
   880 //
       
   881 // Starts animation if possible and sets control to correct state.
       
   882 // ---------------------------------------------------------
       
   883 //
       
   884 void CMsgImageControl::DoPlay( TInt aAnimationStartDelay )
       
   885     {
       
   886     StartAnimation( aAnimationStartDelay );
       
   887     
       
   888     if ( iState != EMsgAsyncControlStateOpening )
       
   889         {
       
   890         SetState( EMsgAsyncControlStatePlaying );
       
   891         }
       
   892     }
       
   893 
       
   894 // ---------------------------------------------------------
       
   895 // CMsgImageControl::DoPause
       
   896 //
       
   897 // Stops animation and sets control to correct state.
       
   898 // ---------------------------------------------------------
       
   899 //
       
   900 void CMsgImageControl::DoPause()
       
   901     {
       
   902     StopAnimation();
       
   903     
       
   904     SetState( EMsgAsyncControlStatePaused );
       
   905     }
       
   906 
       
   907 // ---------------------------------------------------------
       
   908 // CMsgImageControl::CalculateMaxSize
       
   909 // ---------------------------------------------------------
       
   910 //
       
   911 void CMsgImageControl::CalculateMaxSize()
       
   912     {
       
   913     TAknLayoutRect maxSizeLayout;
       
   914     maxSizeLayout.LayoutRect( MsgEditorCommons::MsgDataPane(),
       
   915                               AknLayoutScalable_Apps::msg_data_pane_g1().LayoutLine() );
       
   916     
       
   917     iMaxSize = maxSizeLayout.Rect().Size();
       
   918     
       
   919     // Make sure "iMaxSize" is multiple of "iBaseLine"
       
   920     iMaxSize.iHeight = iBaseLine * ( iMaxSize.iHeight / iBaseLine );
       
   921     }
       
   922 
       
   923 // ---------------------------------------------------------
       
   924 // CMsgImageControl::HitRegionContains
       
   925 // 
       
   926 // Note! CONE will do final verification if control is really hit so
       
   927 //       not need to do it here.
       
   928 // ---------------------------------------------------------
       
   929 //
       
   930 #ifdef RD_SCALABLE_UI_V2
       
   931 TBool CMsgImageControl::HitRegionContains( const TPoint& aPoint, 
       
   932                                      const CCoeControl& /*aControl*/ ) const
       
   933     {
       
   934     TBool result( EFalse );
       
   935     
       
   936     CCoeControl* visiblePlaceholder = VisiblePlaceholder();
       
   937     
       
   938     if ( visiblePlaceholder )
       
   939         {
       
   940         result = visiblePlaceholder->Rect().Contains( aPoint );
       
   941         }
       
   942     else
       
   943         {
       
   944         result = iBitmapControl->Rect().Contains( aPoint );
       
   945         }
       
   946         
       
   947     return result;
       
   948     }
       
   949 #else
       
   950 TBool CMsgImageControl::HitRegionContains( const TPoint& /*aPoint*/, 
       
   951                                      const CCoeControl& /*aControl*/ ) const
       
   952     {
       
   953     return EFalse;
       
   954     }
       
   955 #endif
       
   956 
       
   957 
       
   958 // ---------------------------------------------------------
       
   959 // CMsgImageControl::FrameSize
       
   960 //
       
   961 // Returns the framesize
       
   962 // ---------------------------------------------------------
       
   963 //
       
   964 EXPORT_C TSize CMsgImageControl::FrameSize()
       
   965     {
       
   966     return iFrame->FrameSize();
       
   967     }
       
   968 
       
   969 // ---------------------------------------------------------
       
   970 // CMsgImageControl::StartAnimation
       
   971 //
       
   972 // Starts animation if possible.
       
   973 // ---------------------------------------------------------
       
   974 //
       
   975 void CMsgImageControl::StartAnimation( TInt aAnimationStartDelay )
       
   976     {
       
   977     iLoopTimer->Cancel();
       
   978     
       
   979     if ( iEngine && 
       
   980          IsAnimation() && 
       
   981          !IsOffScreen() &&
       
   982          iLoopCount != iCurrentLoop )
       
   983         {    
       
   984         iAnimationState = EAnimationPlaying;
       
   985             
       
   986         if ( aAnimationStartDelay == 0 )
       
   987             {
       
   988             iEngine->Play();
       
   989             }
       
   990         else 
       
   991             {
       
   992             iLoopTimer->Start( aAnimationStartDelay,
       
   993                                aAnimationStartDelay,
       
   994                                TCallBack( DoStartLoop, this ) );
       
   995             }
       
   996         }
       
   997     }
       
   998 
       
   999 // ---------------------------------------------------------
       
  1000 // CMsgImageControl::StopAnimation
       
  1001 //
       
  1002 // Stops animation if possible.
       
  1003 // ---------------------------------------------------------
       
  1004 //
       
  1005 void CMsgImageControl::StopAnimation()
       
  1006     {
       
  1007     iLoopTimer->Cancel();
       
  1008     
       
  1009     if ( iEngine &&  
       
  1010          IsAnimation() )
       
  1011         {
       
  1012         iEngine->Stop();
       
  1013         iAnimationState = EAnimationStopped;
       
  1014         }
       
  1015     }
       
  1016 
       
  1017 // ---------------------------------------------------------
       
  1018 // CMsgImageControl::PauseAnimation
       
  1019 //
       
  1020 // Pauses animation if possible.
       
  1021 // ---------------------------------------------------------
       
  1022 //
       
  1023 void CMsgImageControl::PauseAnimation()
       
  1024     {
       
  1025     StopAnimation();
       
  1026     iAnimationState = EAnimationPaused;
       
  1027     }
       
  1028 
       
  1029 // ---------------------------------------------------------
       
  1030 // CMsgImageControl::DoStartLoop
       
  1031 //
       
  1032 // Start new animation loop.
       
  1033 // ---------------------------------------------------------
       
  1034 //
       
  1035 TInt CMsgImageControl::DoStartLoop( TAny* aObject )
       
  1036     {
       
  1037     // cast, and call non-static function
       
  1038     CMsgImageControl* control = static_cast<CMsgImageControl*>( aObject );
       
  1039     control->StartLoop();
       
  1040     
       
  1041     return KErrNone;
       
  1042     }
       
  1043 
       
  1044 // ---------------------------------------------------------
       
  1045 // CMsgImageControl::StartLoop
       
  1046 //
       
  1047 // Start new animation loop.
       
  1048 // ---------------------------------------------------------
       
  1049 //
       
  1050 void CMsgImageControl::StartLoop()
       
  1051     {
       
  1052     if ( iAnimationState == EAnimationPlaying )
       
  1053         {
       
  1054         StartAnimation( 0 );
       
  1055         }
       
  1056     else
       
  1057         {
       
  1058         iLoopTimer->Cancel();
       
  1059         }
       
  1060     }
       
  1061 
       
  1062 //  End of File