idlehomescreen/widgetmanager/src/wmimageconverter.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 15 Mar 2010 12:39:47 +0200
branchRCL_3
changeset 16 9674c1a575e9
parent 15 ff572dfe6d86
child 38 79311d856354
permissions -rw-r--r--
Revision: 201009 Kit: 201010

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies)..
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
* CWmImageConverter implementation
*
*/

#include <fbs.h>
#include <eikdef.h>
#include <eikenv.h>
#include <bautils.h>
#include <imageconversion.h>
#include <bitmaptransforms.h>
#include <AknIconUtils.h>
#include <AknsSkinInstance.h>
#include <AknsUtils.h>
#include <avkon.mbg>
#include <apgcli.h>
#include <SVGEngineInterfaceImpl.h>
#include <widgetregistryconstants.h> // KWidgetUidLowerBound, KWidgetUidUpperBound

#include "wmimageconverter.h"

_LIT( KSkin, 		  "skin" );
_LIT( KMif, 		  "mif" );
_LIT( KUid,           "uid" );
_LIT( KColon,		  ":" );
_LIT( KSvgExt,        ".svg" );
_LIT( KHexPrefix,     "0x" );
const TUint KLeftParenthesis = '(';

// ---------------------------------------------------------
// CWmImageConverter::NewL
// ---------------------------------------------------------
//
CWmImageConverter* CWmImageConverter::NewL( MConverterObserver* aObserver )
    {
    CWmImageConverter* self = 
        new(ELeave) CWmImageConverter();
    CleanupStack::PushL( self );    
    self->ConstructL( aObserver );
    CleanupStack::Pop(self);
    return self; 
    }

// ---------------------------------------------------------
// CWmImageConverter::CWmImageConverter 
// ---------------------------------------------------------
//
CWmImageConverter::CWmImageConverter() 
    : CActive( EPriorityStandard )
    {
    iState = EIdle;
    iBitmap = NULL;
    iMask = NULL;
    iObserver = NULL;
    iConversionMethod = EUnrecognized;
    CActiveScheduler::Add( this );
    }

// ---------------------------------------------------------
// CWmImageConverter::ConstructL
// ---------------------------------------------------------
//
void CWmImageConverter::ConstructL( MConverterObserver* aObserver )
    {
    User::LeaveIfError( iFs.Connect() );
    iFs.ShareProtected();
    iScaler = CBitmapScaler::NewL();
    iObserver = aObserver;
    }

// ---------------------------------------------------------
// CWmImageConverter::~CWmImageConverter
// ---------------------------------------------------------
//
CWmImageConverter::~CWmImageConverter()
    {
    Cancel();
    delete iImageDecoder;
    iFs.Close(); 
    if ( iBitmap ) 
        {
        delete iBitmap;
        iBitmap = NULL;
        }
    if ( iMask )
        {
        delete iMask; 
        iMask = NULL;
        }
    delete iScaler;
    }

// ---------------------------------------------------------
// CWmImageConverter::HandleIconString
// ---------------------------------------------------------
//
TInt CWmImageConverter::HandleIconString( 
                            TInt aWidth, TInt aHeight, 
                            const TDesC& aIconStr )
    {
    TInt err( KErrNone );
    TRAP( err, HandleIconStringL( aWidth, aHeight, aIconStr ); );
    if ( KErrNone != err )
        {
        iState = EFailed;
        if ( iBitmap ) 
            {
            delete iBitmap;
            iBitmap = NULL;
            }
        if ( iMask )
            {
            delete iMask; 
            iMask = NULL;
            }
        }
    return err;
    }

// ---------------------------------------------------------
// CWmImageConverter::HandleIconStringL
// ---------------------------------------------------------
//
void CWmImageConverter::HandleIconStringL( 
                            TInt aWidth, TInt aHeight, 
                            const TDesC& aIconStr )
    {
    iConversionMethod = EUnrecognized;
    iState = EDecoding;
    if ( aIconStr.Length() )
        {
        TAknsItemID skinItemId;
        skinItemId.iMajor = 0;
        skinItemId.iMinor = 0;
        TInt bitmapId( KErrNotFound );
        TInt maskId( KErrNotFound );
        TUid appUid;
        iFilename = KNullDesC;
        iScaleNeeded = EFalse;
        iSize.SetSize( aWidth, aHeight );
        
        if ( ResolveSkinIdAndMifId( 
                aIconStr, skinItemId, bitmapId, maskId, iFilename ) )
            {
            if ( bitmapId >= 0 && skinItemId.iMajor > 0 )
                iConversionMethod = ESkinAndMifIcon;
            else if ( bitmapId >= 0 )
                iConversionMethod = EMifIcon;
            else
                iConversionMethod = ESkinIcon;
            CreateSkinOrMifIconL( 
                    skinItemId, bitmapId, maskId, iFilename );
            }
        else if ( ResolveUid( aIconStr, appUid ) )
            {
            iConversionMethod = EUidIcon;
            CreateIconFromUidL( appUid );
            }
        else if ( EndsWith( aIconStr, KSvgExt ) )
            {
            // filename_with_full_path.svg
            iConversionMethod = ESvgIcon;
            CreateIconFromSvgL( aIconStr );
            }
        else if ( BaflUtils::FileExists( iFs, aIconStr ) )
            {
            // filename_with_full_path.png/jpg
            iConversionMethod = EImageIcon;
            CreateIconFromOtherL( aIconStr );
            }
        else
            {
            User::Leave( KErrArgument );
            }
        }
    else
        {            
        User::Leave( KErrArgument );
        }
    }

// ---------------------------------------------------------
// CWmImageConverter::CreateIconFromUidL
// ---------------------------------------------------------
//
void CWmImageConverter::CreateIconFromUidL( const TUid& aUid )
    {
    CFbsBitmap* bitmap = NULL;
    CFbsBitmap* mask = NULL;
   
   
    if ( aUid.iUid >= KWidgetUidLowerBound &&
       aUid.iUid < KWidgetUidUpperBound  )
        {
        RApaLsSession lsSession;
        User::LeaveIfError( lsSession.Connect() );
        CleanupClosePushL( lsSession );
        
        const TInt KAppSizeArraySize = 3;
        CArrayFixFlat<TSize>* sizeArray = new (ELeave)
            CArrayFixFlat<TSize>( KAppSizeArraySize );
        CleanupStack::PushL( sizeArray );

        User::LeaveIfError( lsSession.GetAppIconSizes( aUid, *sizeArray ) );
        
        // there should be atleast one size available
        if ( sizeArray->Count() == 0 ){ User::Leave( KErrNotReady ); };
        
        TSize size(0,0);
        for( TInt i=0; i < sizeArray->Count(); i++ )
            {
            TSize s = (*sizeArray)[i];
            if ( size.iWidth < s.iWidth || size.iHeight < s.iHeight )
                { size = s; }
            if ( size == iSize ) { break; }
            }

        CApaMaskedBitmap* maskedBmp = CApaMaskedBitmap::NewLC();
        User::LeaveIfError( lsSession.GetAppIcon( aUid, size, *maskedBmp ) );
        
        // handle bitmap
        iBitmap = new ( ELeave ) CFbsBitmap;
        User::LeaveIfError( iBitmap->Create( 
                maskedBmp->SizeInPixels(), 
                maskedBmp->DisplayMode() ) );

        // scale bitmap
        ScaleBitmapL( iSize, iBitmap, maskedBmp );  

        // handle mask
        if ( maskedBmp->Mask() )
            {
            iMask = new ( ELeave ) CFbsBitmap;
            User::LeaveIfError( iMask->Create( 
                    maskedBmp->Mask()->SizeInPixels(), 
                    maskedBmp->Mask()->DisplayMode() ) );
            
            // scale mask
            ScaleBitmapL( iSize, iMask, maskedBmp->Mask() );
            }
        
        // cleanup
        CleanupStack::PopAndDestroy( maskedBmp );
        CleanupStack::PopAndDestroy( sizeArray ); 
        CleanupStack::PopAndDestroy( &lsSession );
        
        // notify
        iState = EIdle;
        iObserver->NotifyCompletion( KErrNone );
        }
    else if ( aUid.iUid != KNullUid.iUid )
        {
        MAknsSkinInstance* skin = AknsUtils::SkinInstance();
        TInt err( KErrNone );
        TRAP( err,
                {
                AknsUtils::CreateAppIconLC( skin, aUid,
                        EAknsAppIconTypeContext, bitmap, mask );
                CleanupStack::Pop( 2 ); // for trap
                }
            );
        
        if( KErrNone != err )
            {
            // If icon is not created, try to create default application icon
            AknsUtils::CreateIconLC( skin,
                KAknsIIDQgnMenuUnknownLst, bitmap, mask,
                AknIconUtils::AvkonIconFileName(),
                EMbmAvkonQgn_menu_unknown_lst,
                EMbmAvkonQgn_menu_unknown_lst_mask );
            CleanupStack::Pop( 2 ); // for trap
            }
        
        iBitmap = bitmap;
        iMask = mask;
                
        err = AknIconUtils::SetSize( iBitmap , iSize, EAspectRatioNotPreserved );
        if ( KErrNone == err )
            {
            err = AknIconUtils::SetSize( iMask , iSize, EAspectRatioNotPreserved );
            }

        // notify observer
        iState = EIdle;
        iObserver->NotifyCompletion( err );
        }
    else
        {
        iState = EIdle;
        User::Leave( KErrArgument );
        }
    }

// ---------------------------------------------------------
// CWmImageConverter::CreateIconFromSvgL
// ---------------------------------------------------------
//
void CWmImageConverter::CreateIconFromSvgL( const TDesC& aFileName )
    {
    if ( iBitmap )
        {
        delete iBitmap;
        iBitmap = NULL;
        }
    if ( iMask )
        {
        delete iMask;
        iMask = NULL;
        }

    TDisplayMode mode = CEikonEnv::Static()->ScreenDevice()->DisplayMode();
    if ( mode >= ERgb ) // currently svg engine doesn't render correctly
        { mode = EColor16M; } // in this or above mode ( ou1cimx1#229434 )
    TFontSpec fontspec;
    
    CFbsBitmap* frameBuffer = new ( ELeave ) CFbsBitmap;
    CleanupStack::PushL( frameBuffer );
    frameBuffer->Create( iSize, mode );
    
    CSvgEngineInterfaceImpl* svgEngine = CSvgEngineInterfaceImpl::NewL( 
            frameBuffer, NULL, fontspec );
    CleanupStack::PushL( svgEngine );
    
    svgEngine->SetDRMMode( EFalse );

    TInt domHandle;
    CheckSvgErrorL( svgEngine->PrepareDom( aFileName, domHandle ) );
    
    CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;    
    CleanupStack::PushL( bitmap );
    User::LeaveIfError( bitmap->Create( iSize, mode ) );
    
    CFbsBitmap* mask = new(ELeave) CFbsBitmap;    
    CleanupStack::PushL( mask );
    User::LeaveIfError( mask->Create( iSize, EGray256 ) );
    
    CheckSvgErrorL( svgEngine->UseDom( domHandle, bitmap, mask ) );

    MSvgError* err;
    svgEngine->Start( err );
    CheckSvgErrorL( err );
    
    CheckSvgErrorL( svgEngine->UseDom( domHandle, NULL, NULL ) );
    CheckSvgErrorL( svgEngine->DeleteDom( domHandle ) );

    CleanupStack::Pop( mask );
    CleanupStack::Pop( bitmap );
    CleanupStack::PopAndDestroy( svgEngine );
    CleanupStack::PopAndDestroy( frameBuffer );
    
    iBitmap = bitmap;
    iMask = mask;
    iState = EIdle;
    iObserver->NotifyCompletion( KErrNone );
    }

// ---------------------------------------------------------
// CWmImageConverter::CheckSvgErrorL
// ---------------------------------------------------------
//
void CWmImageConverter::CheckSvgErrorL( MSvgError* aError )
    {
    if ( aError )
        {
        User::LeaveIfError( aError->SystemErrorCode() );
        }
    }

// ---------------------------------------------------------
// CWmImageConverter::CreateIconFromOtherL
// ---------------------------------------------------------
//
void CWmImageConverter::CreateIconFromOtherL( const TDesC& aFileName )
    {
    if ( IsActive() )
        {
        User::Leave( KErrNotReady );
        }
    
    if ( iImageDecoder ) delete iImageDecoder; iImageDecoder = NULL;
    if (iBitmap) {delete iBitmap; iBitmap = NULL;}
    if (iMask) {delete iMask; iMask = NULL;}
    
    iFilename.Copy( aFileName );
    
    // create the decoder
    iImageDecoder = CImageDecoder::FileNewL( iFs, iFilename );
    
    TSize size = iImageDecoder->FrameInfo().iOverallSizeInPixels;

    // create the destination bitmap
    iBitmap = new (ELeave) CFbsBitmap();
    iBitmap->Create( size,
                     iImageDecoder->FrameInfo().iFrameDisplayMode ); 
    
    iMask = new (ELeave) CFbsBitmap();
    iMask->Create( size, EGray256 ); 

    if ( size != iSize )
        {
        iScaleNeeded = ETrue;
        }

    // start conversion to bitmap
    iImageDecoder->Convert( &iStatus, *iBitmap, *iMask );
    SetActive();
    }

// ---------------------------------------------------------
// CWmImageConverter::DoCancel
// ---------------------------------------------------------
//
void CWmImageConverter::DoCancel()
    {
    if( iState == EDecoding && 
       iConversionMethod == EImageIcon )
        {
        iImageDecoder->Cancel();
        iState = EIdle;
        if ( iObserver )
            {            
            iObserver->NotifyCompletion( KErrCancel );
            }
        }    
    else if( iState == EScalingBitmap ||
        iState == EScalingMask )
        {
        iScaler->Cancel();
        iState = EIdle;
        if ( iObserver )
            {            
            iObserver->NotifyCompletion( KErrCancel );
            }
        }    
    else
        {
        // State is EIdle, do nothing
        }    
    iScaleNeeded = EFalse;
    }

// ---------------------------------------------------------
// CWmImageConverter::RunL
// ---------------------------------------------------------
//
void CWmImageConverter::RunL()
    {
    switch( iState ) 
        {
        case EDecoding:
            {
            if( iStatus.Int() == KErrNone )
                {
                if ( iScaleNeeded )
                    {
                    ScaleBitmap( iSize.iWidth, iSize.iHeight );
                    }
                else
                    {
                    iState = EIdle;
                    if ( iObserver )
                        {
                        iObserver->NotifyCompletion( KErrNone );
                        }
                    }
                break;
                }
            else if( iStatus.Int() == KErrUnderflow ) 
                {
                iImageDecoder->ContinueConvert( &iStatus );
                SetActive();
                break;
                }
            else if ( iStatus.Int() == KErrCorrupt )
                {
                iState = EIdle;
                iScaleNeeded = EFalse;
                if ( iBitmap )
                    {
                    delete iBitmap;
                    iBitmap = NULL;
                    }
                if ( iMask )
                    {
                    delete iMask;
                    iMask = NULL;
                    }
                if ( iObserver )
                    {
                    iObserver->NotifyCompletion( KErrCorrupt );
                    }
                break;
                }
            else
                {
                // Unknown error
                iState = EIdle;
                iScaleNeeded = EFalse;
                if ( iBitmap )
                    {
                    delete iBitmap;
                    iBitmap = NULL;
                    }
                if ( iMask )
                    {
                    delete iMask;
                    iMask = NULL;
                    }
                if ( iObserver )
                    {
                    iObserver->NotifyCompletion( iStatus.Int() );
                    }
                break;
                }
            }
        case EScalingBitmap:
            {
            if( iStatus.Int() == KErrNone && iMask )
                {
                ScaleMask( iSize.iWidth, iSize.iHeight );
                }
            else
                {
                iState = EIdle;
                iScaleNeeded = EFalse;
                if ( iObserver )
                    {
                    iObserver->NotifyCompletion( iStatus.Int() );
                    }                
                }
            break;
            }
        case EScalingMask:
            {
            iState = EIdle;
            iScaleNeeded = EFalse;
            if ( iObserver )
                {
                iObserver->NotifyCompletion( iStatus.Int() );
                }
            break;
            }
        default:
            break;
        }   
    }

// ---------------------------------------------------------
// CWmImageConverter::RunError
// ---------------------------------------------------------
//
TInt CWmImageConverter::RunError(TInt /*aError*/)
    {
    // Our RunL does not contain any method calls that would leave, so this method
    // should never be called.
    iScaleNeeded = EFalse;
    return KErrNone;
    }

// ---------------------------------------------------------
// CWmImageConverter::ScaleBitmap
// ---------------------------------------------------------
//
void CWmImageConverter::ScaleBitmap( TInt aWidth, TInt aHeight )
    {
    if ( !IsActive() && 
         iBitmap &&
        ( iState == EDecoding || iState == EIdle ) )
        {
        iState = EScalingBitmap;
        // the maintain aspect ratio is by default set to true
        iScaler->Scale( &iStatus, *iBitmap, TSize( aWidth,aHeight ), EFalse );        
        SetActive();
        }
    }

// ---------------------------------------------------------
// CWmImageConverter::ScaleMask
// ---------------------------------------------------------
//
void CWmImageConverter::ScaleMask( TInt aWidth, TInt aHeight )
    {
    if ( !IsActive() && 
        iState == EScalingBitmap &&
        iMask )
        {
        iState = EScalingMask;
        // the maintain aspect ratio is by default set to true
        iScaler->Scale( &iStatus, *iMask, TSize(aWidth,aHeight), EFalse );        
        SetActive();
        }
    }

// ---------------------------------------------------------
// CWmImageConverter::Bitmap
// ---------------------------------------------------------
//
CFbsBitmap* CWmImageConverter::Bitmap()
    {
    CFbsBitmap* bitmap = NULL;
    if (iState == EIdle &&
        iBitmap )
        {
        bitmap = iBitmap;  // ownership taken
        iBitmap = NULL;
        }
    return bitmap;
    }

// ---------------------------------------------------------
// CWmImageConverter::Mask
// ---------------------------------------------------------
//
CFbsBitmap* CWmImageConverter::Mask()
    {
    CFbsBitmap* mask = NULL;
    if (iState == EIdle &&
        iMask )
        {
        mask = iMask;  // ownership taken
        iMask = NULL;
        }
    return mask;
    }

// ---------------------------------------------------------
// CWmImageConverter::EndsWith
// ---------------------------------------------------------
//
TBool CWmImageConverter::EndsWith( const TDesC& aString, 
                                const TDesC& aPattern )
    {
    return ( aString.Right( aPattern.Length() ) == aPattern );
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::ResolveUid
// ---------------------------------------------------------------------------
//
TBool CWmImageConverter::ResolveUid( 
                const TDesC& aPath, TUid& aUid )
    {
    // Syntax: uid(0x12345678)
    TInt error = KErrNotFound;
    TInt pos = aPath.FindF( KUid );
    if( pos == 0 )
        {
        // Skip uid token
        pos += KUid().Length();

        // Initialize lexer
        TLex lex( aPath.Mid( pos ) );
        lex.SkipSpaceAndMark();
        
        // Check left parenthesis
        if ( lex.Get() == KLeftParenthesis )
            {
            error = ParseNextUint( lex, (TUint&)aUid.iUid );
            }
        }
    
    return (error == KErrNone );
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::ResolveSkinId
// ---------------------------------------------------------------------------
//
TBool CWmImageConverter::ResolveSkinId( 
                const TDesC& aPath, TAknsItemID& aItemId )
    {
    // Syntax: skin(major minor)
    TInt error = KErrNotFound;
    TInt pos = aPath.FindF( KSkin );
    if( pos == 0 )
        {
        // Skip skin token
        pos += KSkin().Length();

        // Initialize lexer
        TLex lex( aPath.Mid( pos ) );
        lex.SkipSpaceAndMark();
        
        // Check left parenthesis
        if ( lex.Get() == KLeftParenthesis )
           {
           TUint majorId = 0;
           TUint minorId = 0;
           error = ParseNextUint( lex, majorId );
           error |= ParseNextUint( lex, minorId );
           aItemId.Set( majorId, minorId );
           }        
        }

    return (error == KErrNone );
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::ResolveMifId
// ---------------------------------------------------------------------------
//
TBool CWmImageConverter::ResolveMifId( 
                const TDesC& aPath, TInt& aBitmapId,
                TInt& aMaskId, TDes& aFileName )
    {
    // Syntax: mif(filename bimapId maskId)
   TInt error = KErrNotFound;
   TInt pos = aPath.FindF( KMif );
   if( pos == 0 )
        {
        // Skip mif token
        pos += KMif().Length();
        // Initialize lexer
        TLex lex( aPath.Mid( pos ) );
        lex.SkipSpaceAndMark();
        
        // Check left parenthesis
        if ( lex.Get() == KLeftParenthesis )
           {
           lex.SkipSpaceAndMark();
           lex.SkipCharacters();
           // Resolve MifFile name
           aFileName.Copy(lex.MarkedToken());
           if( aFileName.Length()!= 0)
               {
               TUint bitmap, mask;
               error = ParseNextUint( lex, bitmap );
               ParseNextUint( lex, mask ); // mask is not mandatory
               aBitmapId = bitmap;
               aMaskId = mask;
               }
           }        
        }    
    return ( error == KErrNone );
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::ResolveSkinIdAndMifId
// ---------------------------------------------------------------------------
//
TBool CWmImageConverter::ResolveSkinIdAndMifId( 
                const TDesC& aPath, TAknsItemID& aItemId,
                TInt& aBitmapId, TInt& aMaskId, TDes& aFileName )
   {
   // Syntax: skin(major minor):mif(filename bimapId maskId) 
   TBool result = ResolveSkinId( aPath, aItemId );
   if ( result )
	   {
	   TInt pos = aPath.FindF( KColon );
	   if ( pos != KErrNotFound )
	       {
	       TPtrC ptr = aPath.Mid( pos+1 );
	       result = ResolveMifId( ptr, aBitmapId, aMaskId, aFileName );
	       }
	   }
   else
       {
       result = ResolveMifId( aPath, aBitmapId, aMaskId, aFileName );
       }
   return result;
   }

// ---------------------------------------------------------------------------
// CWmImageConverter::CreateSkinOrMifIconL
// ---------------------------------------------------------------------------
//
void CWmImageConverter::CreateSkinOrMifIconL( 
                const TAknsItemID& aItemId, TInt aBitmapId, 
                TInt aMaskId, const TDesC& aFileName )
    {
    iFilename = aFileName;
    CFbsBitmap* bitmap = NULL;
    CFbsBitmap* mask = NULL;
    
    // Load from skin 
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    if ( skin && aItemId.iMajor != 0 && aItemId.iMinor != 0 )
        {
        TInt err( KErrNone );
        CAknsMaskedBitmapItemData* itemData = NULL;
        TRAP( err, itemData = 
                    static_cast<CAknsMaskedBitmapItemData*>(
                    skin->CreateUncachedItemDataL( aItemId, EAknsITMaskedBitmap ) ); );
        if( itemData && KErrNone == err )
            {
            CleanupStack::PushL( itemData );
            // Detach bitmaps
            bitmap = itemData->Bitmap();
            itemData->SetBitmap( NULL );
            mask = itemData->Mask();
            itemData->SetMask( NULL );
            CleanupStack::PopAndDestroy( itemData );
            }
        else
            {
            // look in imagetable
            CAknsImageTableItemData* iconData = NULL;
            TRAP( err, iconData = static_cast<CAknsImageTableItemData*>(
                            skin->CreateUncachedItemDataL( aItemId, EAknsITImageTable ) ); );
            if( iconData && KErrNone == err )
                {
                CleanupStack::PushL( iconData );
                if( iconData->NumberOfImages() )
                    {                        
                    TAknsItemID iconIId;
                    iconIId.Set( iconData->ImageIID(0) );
                    TRAP( err, AknsUtils::CreateIconL( 
                            skin, iconIId, bitmap, mask, KNullDesC, -1, -1 ); );
                    }
                CleanupStack::PopAndDestroy( iconData );
                }
            }
        
        if ( KErrNone == err && bitmap )
            {
            TInt err = AknIconUtils::SetSize( bitmap , iSize, EAspectRatioNotPreserved );
            if ( KErrNone == err  )
                {
                if ( mask )
                    {
                    err = AknIconUtils::SetSize( mask , iSize, EAspectRatioNotPreserved );
                    }
                iBitmap = bitmap;
                iMask = mask;
                iState = EIdle;
                // notify observer                    
                iObserver->NotifyCompletion( KErrNone );
                return;
                }
            else
                {
                if ( bitmap ) { delete bitmap; bitmap = NULL; }
                if ( mask ){ delete mask; mask = NULL; }
                }
            }
        }
    
    if( aBitmapId != KErrNotFound && !bitmap && 
       aFileName.Length() && BaflUtils::FileExists( iFs, aFileName ) )
        {
        if ( aMaskId != KErrNotFound )
          {
          // Create icon from Mif filename , bitmap id and mask id          
          AknIconUtils::CreateIconL(
                  bitmap, mask, *this, aBitmapId, aMaskId );
          }
        else
          {
          bitmap = AknIconUtils::CreateIconL( *this, aBitmapId );
          }
        }
    else
        {
        iState = EIdle;
        User::Leave( KErrArgument );
        }
    
    iBitmap = bitmap;
    iMask = mask;

    TInt err = AknIconUtils::SetSize( iBitmap , iSize, EAspectRatioNotPreserved );
    if ( KErrNone == err && iMask )
        {
        err = AknIconUtils::SetSize( iMask , iSize, EAspectRatioNotPreserved );
        }
    
    iState = EIdle;
    // notify observer
    iObserver->NotifyCompletion( err );
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::ParseNextUint()
// ---------------------------------------------------------------------------
//
TInt CWmImageConverter::ParseNextUint( TLex& aLex, TUint& aValue )
    {
    TInt error = KErrNone;
    aLex.SkipSpaceAndMark();
    aLex.SkipCharacters();

    TPtrC mtoken = aLex.MarkedToken();
    TInt pos = mtoken.FindF( KHexPrefix );
    if ( pos == 0 )
        {
		TLex innerLex( mtoken.Mid( KHexPrefix().Length() ) );
        error = innerLex.Val( aValue, EHex );
        }
    else
        {
        TLex innerLex( mtoken );
        error = innerLex.Val( aValue, EDecimal );
        }

    return error;
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::SetLogoSize()
// ---------------------------------------------------------------------------
//
void CWmImageConverter::SetLogoSize( const TSize& aSize )
    {
    iSize = aSize;
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::ConversionMethod()
// ---------------------------------------------------------------------------
//
CWmImageConverter::TConversionMethod CWmImageConverter::ConversionMethod()
    {
    return iConversionMethod;
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::RetrieveIconFileHandleL
// ---------------------------------------------------------------------------
//
void CWmImageConverter::RetrieveIconFileHandleL( 
    RFile& aFile, const TIconFileType /*aType*/ )
    {
	TInt err = aFile.Open( iFs, iFilename, 
	        EFileRead | EFileShareReadersOnly );
	if ( KErrNone != err )
	    {
        iState = EIdle;
        User::Leave( err );
	    }
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::DoesScaleBitmapUseFallBack
// ---------------------------------------------------------------------------
//
TBool CWmImageConverter::DoesScaleBitmapUseFallBack( CFbsBitmap* aSrcBitmap )
    {
    if ( !aSrcBitmap )
        {
        return EFalse;
        }

    TDisplayMode displayMode = aSrcBitmap->DisplayMode();
    TBool fallbackOnly = EFalse;

    switch ( displayMode )
        {
        case EGray2:
        case EGray4:
        case EGray16:
        case EColor16:
        case EColor16M:
        case ERgb:
        case EColor16MA:
            fallbackOnly = ETrue;
            break;
        case EGray256:
        case EColor4K:
        case EColor64K:
        case EColor256:
        case EColor16MU:
            // These are the supported modes
            break;
        default:
            fallbackOnly = ETrue;
        }

    return fallbackOnly;
    }


// ---------------------------------------------------------------------------
// CWmImageConverter::ScaleBitmapL
// ---------------------------------------------------------------------------
//
void CWmImageConverter::ScaleBitmapL( 
                            const TSize& aSize,
                            CFbsBitmap* aTrgBitmap,
                            CFbsBitmap* aSrcBitmap )
    {
    if ( !aSrcBitmap ) User::Leave( KErrArgument );
    if ( !aTrgBitmap ) User::Leave( KErrArgument );
    if ( aSrcBitmap->DisplayMode() != aTrgBitmap->DisplayMode() )
        {
        User::Leave( KErrArgument );
        }
    
    // make target to correct size
    if ( aTrgBitmap->SizeInPixels() != aSize )
        {
        aTrgBitmap->Resize( aSize );
        }
    
    TRect targetRect( aSize );

    // calculate aspect ratio
    TInt srcHeight = aSrcBitmap->SizeInPixels().iHeight;
    TInt srcWidth = aSrcBitmap->SizeInPixels().iWidth;
    TReal scaleRatio( 1 ); //no scale as defaul
    
    //If any dimension is 0, then we do not bother to scale
    if ( targetRect.Width() > 0 && targetRect.Height() > 0 )
        {
        TReal xRatio = ( ( TReal )srcWidth / ( TReal )targetRect.Width() );
        TReal yRatio = ( ( TReal )srcHeight / ( TReal )targetRect.Height() );
        //Find out appropriate scaling factor
        xRatio > yRatio ? ( scaleRatio = xRatio ) : ( scaleRatio = yRatio );
        }

    //Scale the size for target bitmap
    targetRect.SetHeight( srcHeight / scaleRatio );
    targetRect.SetWidth( srcWidth / scaleRatio );    
    
    TSize trgBitmapSize = aTrgBitmap->SizeInPixels();
    
    // calculate the valid drawing area
    TRect drawRect = targetRect;
    drawRect.Intersection( TRect( TPoint( 0, 0 ), trgBitmapSize ) );

    if( drawRect.IsEmpty() || 
        aSrcBitmap->SizeInPixels().iHeight <= 0 || 
        aSrcBitmap->SizeInPixels().iWidth <= 0 )
        {
        User::Leave( KErrArgument );
        }

    TSize srcSize = aSrcBitmap->SizeInPixels();

    TBool srcTemporary = EFalse;
    if ( aSrcBitmap->IsRomBitmap() )
        {
        srcTemporary = ETrue;
        }

    TDisplayMode displayMode = aSrcBitmap->DisplayMode();
    TBool fallbackOnly = DoesScaleBitmapUseFallBack( aSrcBitmap );

    if ( fallbackOnly )
        {
        CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( aTrgBitmap );
        CleanupStack::PushL( dev );
        CFbsBitGc* gc = NULL;
        User::LeaveIfError( dev->CreateContext( gc ) );
        CleanupStack::PushL( gc );

        // write alpha information if it exists
        if ( aSrcBitmap->DisplayMode() == EColor16MA )
            {
            gc->SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha );
            }

        // targetRect is used because DrawBitmap handles clipping automatically
        gc->DrawBitmap( targetRect, aSrcBitmap );
        CleanupStack::PopAndDestroy( 2 ); // dev, gc
        return;
        }

    // Heap lock for FBServ large chunk to prevent background
    // compression of aSrcBitmap after if IsCompressedInRAM returns EFalse
    aSrcBitmap->LockHeapLC( ETrue ); // fbsheaplock
    TBool fbsHeapLock = ETrue;
    if ( aSrcBitmap->IsCompressedInRAM() )
        {
        srcTemporary = ETrue;
        }

    CFbsBitmap* realSource = aSrcBitmap;
    if ( srcTemporary )
        {
        CleanupStack::PopAndDestroy(); // fbsheaplock
        fbsHeapLock = EFalse;

        realSource = new ( ELeave ) CFbsBitmap();
        CleanupStack::PushL( realSource );
        User::LeaveIfError(
            realSource->Create( srcSize, aSrcBitmap->DisplayMode() ) );
        CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( realSource );
        CleanupStack::PushL( dev );
        CFbsBitGc* gc = NULL;
        User::LeaveIfError( dev->CreateContext( gc ) );
        CleanupStack::PushL( gc );
        gc->BitBlt( TPoint( 0, 0 ), aSrcBitmap );
        CleanupStack::PopAndDestroy( 2 ); // dev, gc
        }

    if ( !fbsHeapLock )
        {
        // Heap lock for FBServ large chunk is only needed with large bitmaps.
        if ( realSource->IsLargeBitmap() || aTrgBitmap->IsLargeBitmap() )
            {
            aTrgBitmap->LockHeapLC( ETrue ); // fbsheaplock
            }
        else
            {
            CleanupStack::PushL( ( TAny* )NULL );
            }
        }

    TUint32* srcAddress = realSource->DataAddress();
    TUint32* trgAddress = aTrgBitmap->DataAddress();

    const TInt xSkip = ( srcSize.iWidth << 8 ) / targetRect.Width();
    const TInt ySkip = ( srcSize.iHeight << 8 ) / targetRect.Height();

    const TInt drawWidth  = drawRect.Width();
    const TInt drawHeight = drawRect.Height();

    TRect offsetRect( targetRect.iTl, drawRect.iTl );
    const TInt yPosOffset = ySkip * offsetRect.Height();
    const TInt xPosOffset = xSkip * offsetRect.Width();

    if ( ( displayMode == EGray256 ) || ( displayMode == EColor256 ) )
        {
        TInt srcScanLen8 = CFbsBitmap::ScanLineLength(
            srcSize.iWidth, displayMode );
        TInt trgScanLen8 = CFbsBitmap::ScanLineLength(
            trgBitmapSize.iWidth, displayMode );

        TUint8* trgAddress8 = reinterpret_cast< TUint8* >( trgAddress );

        TInt yPos = yPosOffset;
        // skip left and top margins in the beginning
        trgAddress8 += trgScanLen8 * drawRect.iTl.iY + drawRect.iTl.iX;

        for ( TInt y = 0; y < drawHeight; y++ )
            {
            TUint8* srcAddress8 = reinterpret_cast< TUint8* >( srcAddress ) +
                ( srcScanLen8 * ( yPos >> 8 ) );

            TInt xPos = xPosOffset;
            for ( TInt x = 0; x < drawWidth; x++ )
                {
                *( trgAddress8++ ) = srcAddress8[xPos >> 8];
                xPos += xSkip;
                }

            yPos += ySkip;

            trgAddress8 += trgScanLen8 - drawWidth;
            }
        }
    else if ( displayMode == EColor4K || displayMode == EColor64K )
        {
        TInt srcScanLen16 = CFbsBitmap::ScanLineLength(
            srcSize.iWidth, displayMode ) /2;
        TInt trgScanLen16 = CFbsBitmap::ScanLineLength(
            trgBitmapSize.iWidth, displayMode ) /2;

        TUint16* trgAddress16 = reinterpret_cast< TUint16* >( trgAddress );

        TInt yPos = yPosOffset;
        // skip left and top margins in the beginning
        trgAddress16 += trgScanLen16 * drawRect.iTl.iY + drawRect.iTl.iX;

        for ( TInt y = 0; y < drawHeight; y++ )
            {
            TUint16* srcAddress16 = reinterpret_cast< TUint16* >( srcAddress ) +
                ( srcScanLen16 * ( yPos >> 8 ) );

            TInt xPos = xPosOffset;
            for ( TInt x = 0; x < drawWidth; x++ )
                {
                *( trgAddress16++ ) = srcAddress16[xPos >> 8];
                xPos += xSkip;
                }

            yPos += ySkip;

            trgAddress16 += trgScanLen16 - drawWidth;
            }
        }
    else if ( displayMode == EColor16MU )
        {
        TInt srcScanLen32 = CFbsBitmap::ScanLineLength(
            srcSize.iWidth, displayMode ) /4;
        TInt trgScanLen32 = CFbsBitmap::ScanLineLength(
            trgBitmapSize.iWidth, displayMode ) /4;

        TUint32* trgAddress32 = reinterpret_cast< TUint32* >( trgAddress );

        TInt yPos = yPosOffset;
        // skip left and top margins in the beginning
        trgAddress32 += trgScanLen32 * drawRect.iTl.iY + drawRect.iTl.iX;

        for ( TInt y = 0; y < drawHeight; y++ )
            {
            TUint32* srcAddress32 = reinterpret_cast< TUint32* >( srcAddress ) +
                ( srcScanLen32 * ( yPos >> 8 ) );

            TInt xPos = xPosOffset;
            for ( TInt x = 0; x < drawWidth; x++ )
                {
                *( trgAddress32++ ) = srcAddress32[xPos >> 8];
                xPos += xSkip;
                }

            yPos += ySkip;

            trgAddress32 += trgScanLen32 - drawWidth;
            }
        }
    else
        {
        User::Leave( KErrUnknown );
        }

    CleanupStack::PopAndDestroy(); // fbsheaplock

    if ( srcTemporary )
        {
        CleanupStack::PopAndDestroy(); // realSource
        }
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::Finished
// ---------------------------------------------------------------------------
//
void CWmImageConverter::Finished()
    {
    // finishes using the icon file. No actions needed here.
    }

// ---------------------------------------------------------------------------
// CWmImageConverter::IsProcessing
// ---------------------------------------------------------------------------
//
TBool CWmImageConverter::IsProcessing()
    {
    return ( ( ( iState != EIdle && iState != EFailed ) ||
            IsActive() ) ? ETrue : EFalse );
    }

// End of file