skins/AknSkins/src/AknsUtilsAppIcon.cpp
changeset 0 05e9090e2422
child 2 abcbdabaa4c5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/skins/AknSkins/src/AknsUtilsAppIcon.cpp	Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,530 @@
+/*
+* Copyright (c) 2004-2008 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:  Extension to AknsUtils.
+*
+*/
+
+
+// INCLUDE FILES
+#include "AknsCppPreface.h"
+
+#include <apgcli.h>
+#include <AknIconUtils.h>
+
+#include <avkon.mbg>
+
+#include <AknsUtils.h>
+#include "AknsJavaUtils.h"
+
+#include <AknsItemData.h>
+#include "AknsAppSkinInstance.h"
+#include <AknsImageAttributeData.h>
+#include "AknsDebug.h"
+
+#include "AknInternalIconUtils.h"
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// AknsUtils::CreateAppIconLC
+// -----------------------------------------------------------------------------
+//
+AKNS_EXPORTED_METHOD(AknsUtils::CreateAppIconLC)
+EXPORT_C void AknsUtils::CreateAppIconLC(
+    MAknsSkinInstance* aInstance, TUid aAppUid,
+    TAknsAppIconType aType,
+    CFbsBitmap*& aBitmap, CFbsBitmap*& aMask )
+    {
+    aBitmap = NULL;
+    aMask = NULL;
+
+    if (!aInstance)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    TSize legacySize( 42, 29 );
+    TInt bitmapIndex( 0 );
+    TInt maskIndex( 1 );
+    if( aType == EAknsAppIconTypeContext )
+        {
+        legacySize = TSize( 44, 44 );
+        bitmapIndex = 2;
+        maskIndex = 3;
+        }
+    else if( aType != EAknsAppIconTypeList )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // Make the forthcoming pushes safe (up to level 2)
+    CleanupStack::PushL( static_cast<TAny*>(NULL) );
+    CleanupStack::PushL( static_cast<TAny*>(NULL) );
+    CleanupStack::Pop( 2 );
+
+    // 1. Check if the icon has been configured.
+    TInt ret = KErrNone;
+    TBool configuredIcon = EFalse;
+    //
+    CAknsAppSkinInstance* apskin = static_cast<CAknsAppSkinInstance*>(aInstance);
+    if ( apskin )
+        {
+        TInt config = apskin->IsIconConfiguredL( aAppUid );
+        if ( config > 0 )
+        configuredIcon = ETrue;
+        }
+
+    if ( !configuredIcon )
+        {
+        // 2. Skin-originating icon
+        ret = GetAppIconFromSkin( aInstance, aAppUid, legacySize, aBitmap, aMask );
+        if( ret == KErrNone )
+            {
+            // These pushes are safe
+            CleanupStack::PushL( aBitmap ); // (1)
+            CleanupStack::PushL( aMask ); // (2)
+            return;
+            }
+        }
+    // Cache connected apparc session for future reuse, if not already cached
+    // This is done per appskininstance when necessary...
+    if (!apskin->iCachedApaSession)
+        {
+        apskin->iCachedApaSession = new (ELeave) RApaLsSession;
+        User::LeaveIfError(apskin->iCachedApaSession->Connect());
+        }
+
+    RApaLsSession* lsSession = apskin->iCachedApaSession;
+
+    TBool forceDefaultIcon = EFalse;
+
+    TApaAppInfo appInfo;
+    TFileName filename;
+    // 3. New appicon framework
+    HBufC* filenameBuf = NULL;
+    TBool javaIcon = EFalse;
+    ret = lsSession->GetAppIcon( aAppUid, filenameBuf );
+    if( filenameBuf )
+        {
+        filename.Copy( *filenameBuf );
+        delete filenameBuf;
+        }
+    if( ret == KErrNone )
+        {
+        ret = lsSession->GetAppInfo( appInfo, aAppUid );
+        }
+    if( (ret==KErrNone) && (filename.Length()>2) &&
+        (appInfo.iFullName.Length()>2) )
+        {
+        // Correct drive letter, if necessary
+        if( appInfo.iFullName[1]==':' )
+            {
+            if( filename[1]==':' )
+                {
+                filename[0] = appInfo.iFullName[0];
+                }
+            else if( filename[0]=='\\' )
+                {
+                filename.Insert( 0, appInfo.iFullName.Left(2) );
+                }
+            }
+
+        // check if the icon is java icon
+        javaIcon = AknsJavaUtils::IsJavaIcon(filename);
+
+        if( AknIconUtils::IsMifFile( filename ) )
+            {
+            // SVG icon
+            // SVG always has only one icon
+            bitmapIndex = 0;
+            maskIndex = 1;
+            AknIconUtils::ValidateLogicalAppIconId( filename,
+                bitmapIndex, maskIndex );
+
+            if (javaIcon)
+                {
+                AknsJavaUtils::CreateIconLC(*lsSession, aAppUid, aBitmap,
+                    aMask, bitmapIndex, maskIndex ); // aBitmap, aMask (2)
+                }
+            else
+                {
+                AknIconUtils::CreateIconLC( aBitmap, aMask, filename,
+                    bitmapIndex, maskIndex ); // aBitmap, aMask (2)
+                }
+            AknInternalIconUtils::SetAppIcon(aBitmap); //icon case
+            return;
+            }
+        else
+            {
+            // MBM icon
+            AknIconUtils::ValidateLogicalAppIconId( filename,
+                bitmapIndex, maskIndex );
+            TRAP( ret, AknIconUtils::CreateIconL( aBitmap, aMask, filename,
+                bitmapIndex, maskIndex ) );
+            if( ret == KErrNone )
+                {
+                // These pushes are safe
+                CleanupStack::PushL( aBitmap ); // (1)
+                CleanupStack::PushL( aMask ); // (2)
+                }
+            else
+                {
+                bitmapIndex = 0;
+                maskIndex = 1;
+                AknIconUtils::ValidateLogicalAppIconId( filename,
+                    bitmapIndex, maskIndex );
+                AknIconUtils::CreateIconLC( aBitmap, aMask, filename,
+                    bitmapIndex, maskIndex ); // aBitmap, aMask (2)
+                }
+            AknInternalIconUtils::SetAppIcon(aBitmap); //icon case
+            return;
+            }
+        }
+    else if( ret!=KErrNotSupported )
+        {
+        // New framework, but no icon defined
+        forceDefaultIcon = ETrue;
+        }
+
+    CApaMaskedBitmap* apaBmp = CApaMaskedBitmap::NewLC(); // apaBmp (1)
+    // 3. Old (AIF-based) framework
+    if( !forceDefaultIcon )
+        {
+        TInt apaErr = lsSession->GetAppIcon( aAppUid, legacySize, *apaBmp );
+        // Use default icon if APPARC did not initialize icon bitmaps
+        if( apaErr || (!apaBmp) || (!apaBmp->Mask()) ||
+            (!apaBmp->Handle()) || (!apaBmp->Mask()->Handle()) )
+            {
+            forceDefaultIcon = ETrue;
+            }
+        }
+
+    if( forceDefaultIcon )
+        {
+        // Default icon
+        CleanupStack::PopAndDestroy( 1 ); // apaBmp (0)
+        TAknsItemID iid = KAknsIIDQgnMenuUnknownLst;
+        bitmapIndex = EMbmAvkonQgn_menu_unknown_lst;
+        maskIndex = EMbmAvkonQgn_menu_unknown_lst_mask;
+        if( aType == EAknsAppIconTypeContext )
+            {
+            iid = KAknsIIDQgnMenuUnknownCxt;
+            bitmapIndex = EMbmAvkonQgn_menu_unknown_cxt;
+            maskIndex = EMbmAvkonQgn_menu_unknown_cxt_mask;
+            }
+        AknsUtils::CreateIconLC( aInstance, iid, aBitmap, aMask,
+            AknIconUtils::AvkonIconFileName(), bitmapIndex, maskIndex ); // aBitmap, aMask (2)
+        }
+    else
+        {
+        // AIF-based icon
+        CFbsBitmap* iconOwnedBitmap = new (ELeave) CFbsBitmap();
+        CleanupStack::PushL( iconOwnedBitmap ); // iob (3)
+        CFbsBitmap* iconOwnedMask = new (ELeave) CFbsBitmap();
+        CleanupStack::PushL( iconOwnedMask ); // iom (4)
+        User::LeaveIfError(
+            iconOwnedBitmap->Duplicate( apaBmp->Handle() ) );
+        User::LeaveIfError(
+            iconOwnedMask->Duplicate( apaBmp->Mask()->Handle() ) );
+
+        CAknIcon* tmpIcon = CAknIcon::NewL();
+        CleanupStack::Pop( 2 ); // iom, iob (2)
+        CleanupStack::PopAndDestroy( 1 ); // apaBmp (0)
+
+        // Ownership is transferred
+        tmpIcon->SetBitmap( iconOwnedBitmap );
+        tmpIcon->SetMask( iconOwnedMask );
+        // Ownership of tmpIcon is transferred
+        CAknIcon* appIcon = AknIconUtils::CreateIconL( tmpIcon );
+
+        aBitmap = appIcon->Bitmap();
+        aMask = appIcon->Mask();
+        // Detach and delete
+        appIcon->SetBitmap( NULL );
+        appIcon->SetMask( NULL );
+        delete appIcon;
+
+        // These are both safe
+        CleanupStack::PushL( aBitmap ); // (1)
+        CleanupStack::PushL( aMask ); // (2)
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// AknsUtils::OpenAppIconFile
+// -----------------------------------------------------------------------------
+//
+AKNS_EXPORTED_METHOD(AknsUtils::OpenAppIconFile)
+EXPORT_C TInt AknsUtils::OpenAppIconFile(
+    MAknsSkinInstance* /*aInstance*/, TUid /*aAppUid*/,
+    TAknsAppIconType aType, RFile& /*aFile*/ )
+    {
+    if( aType != EAknsAppIconType3D )
+        {
+        return KErrArgument;
+        }
+
+    return KErrNotSupported;
+    }
+
+// -----------------------------------------------------------------------------
+// AknsUtils::GetAppIcon
+// -----------------------------------------------------------------------------
+//
+AKNS_EXPORTED_METHOD(AknsUtils::GetAppIcon)
+EXPORT_C TInt AknsUtils::GetAppIcon(
+    MAknsSkinInstance* aInstance, TUid aAppUid, TSize aSize,
+    CApaMaskedBitmap& aAppBitmap )
+    {
+    AKNS_TRACE_OBSOLETE("AknsUtils::GetAppIcon (4 param)");
+
+    __ASSERT_DEBUG( aAppBitmap.Mask(),
+        AKNS_DEBUG_PANIC( EAknsDPanicInvalidParameter ) );
+
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* mask = NULL;
+
+    TInt ret = KErrNone;
+    TBool configuredIcon = EFalse;
+
+    if ( !configuredIcon )
+        {
+        ret = GetAppIconFromSkin( aInstance, aAppUid, aSize, bitmap, mask );
+        if( ret == KErrNone )
+            {
+            if( bitmap && mask && bitmap->Handle() && mask->Handle() )
+                {
+                ret = aAppBitmap.Duplicate( bitmap->Handle() );
+                ret |= aAppBitmap.Mask()->Duplicate( mask->Handle() );
+                delete bitmap;
+                delete mask;
+                return ret;
+                }
+            else
+                {
+                // Delete bitmaps and proceed
+                delete bitmap;
+                delete mask;
+                }
+            }
+        }
+
+    RApaLsSession lsSession;
+    ret = lsSession.Connect();
+    if( ret == KErrNone )
+        {
+        ret = lsSession.GetAppIcon( aAppUid, aSize, aAppBitmap );
+        lsSession.Close();
+        if(ret == KErrNone) //icon case
+        	AknInternalIconUtils::SetAppIcon(bitmap); //icon case
+        }
+
+    return ret;
+    } //lint !e1746 GetAppIcon syntax
+
+// -----------------------------------------------------------------------------
+// AknsUtils::GetAppIconFromSkin
+// -----------------------------------------------------------------------------
+//
+TInt AknsUtils::GetAppIconFromSkin(
+    MAknsSkinInstance* aInstance, TUid aAppUid, TSize aSize,
+    CFbsBitmap*& aBitmap, CFbsBitmap*& aMask )
+    {
+    if( !aInstance )
+        {
+        return KErrNotSupported;
+        }
+
+    TAknsItemID iid;
+    iid.Set( EAknsMajorAppIcon, aAppUid.iUid );
+
+    TInt err( KErrNone );
+    TAknsItemID iconIID;
+    TRAP( err, ( iconIID = SelectBestAppIconBitmapL(
+        aSize, aInstance, iid ) ) );
+    if( err )
+        {
+        return err;
+        }
+
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* mask = NULL;
+    TRAPD( createErr,
+        CreateIconL( aInstance, iconIID, bitmap, mask, KNullDesC, -1, -1 ) ); //lint !e645 Initialized
+
+    if( createErr )
+        {
+        delete bitmap;
+        delete mask;
+        return createErr;
+        }
+
+    __ASSERT_DEBUG( bitmap && mask,
+        AKNS_DEBUG_PANIC( EAknsDPanicNotInitialized ) );
+
+	AknInternalIconUtils::SetAppIcon(aBitmap); //icon case
+    aBitmap = bitmap;
+    aMask = mask;
+
+    return KErrNone;
+    } //lint !e1746 GetAppIcon syntax
+
+// -----------------------------------------------------------------------------
+// AknsUtils::SelectBestAppIconBitmapL
+// -----------------------------------------------------------------------------
+//
+TAknsItemID AknsUtils::SelectBestAppIconBitmapL(
+    const TSize& aSize,
+    MAknsSkinInstance* aSkin,
+    const TAknsItemID& aAppIconIID )
+    {
+    TAknsItemID iid;
+    iid.Set( KAknsIIDNone );
+    TInt i;
+
+    CAknsImageTableItemData* iconData = static_cast<CAknsImageTableItemData*>(
+        aSkin->CreateUncachedItemDataL( aAppIconIID, EAknsITImageTable ) );
+    if( !iconData )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    CleanupStack::PushL( iconData );
+
+    TInt numberOfIcons = iconData->NumberOfImages();
+    RArray<TSize> sizeArray;
+    for( i=0; i<numberOfIcons; i++ )
+        {
+        TBool defOwned = EFalse;
+        CAknsImageItemDef* def =
+            static_cast<CAknsImageItemDef*>(
+            static_cast<CAknsAppSkinInstance*>(aSkin)->LookupDef(
+            defOwned, iconData->ImageIID(i), EAknsITImage ) );
+
+        TBool appendError = EFalse;
+
+        if( def && def->Attributes() )
+            {
+            TSize imageSize = def->Attributes()->iSize;
+            if( sizeArray.Append( imageSize ) != KErrNone )
+                {
+                appendError = ETrue;
+                }
+            }
+        else
+            {
+            appendError = ETrue;
+            }
+
+        if( defOwned )
+            {
+            delete def;
+            def = NULL;
+            }
+
+        if( appendError )
+            {
+            sizeArray.Reset();
+            User::Leave( KErrGeneral );
+            }
+        }
+
+    CleanupStack::Pop( iconData );
+
+    // First check for zero size (SVG) or the exact match
+    TInt indexFound = -1;
+    for( i=0; i<numberOfIcons; i++ )
+        {
+        if( (sizeArray[i].iWidth==aSize.iWidth) &&
+            (sizeArray[i].iHeight==aSize.iHeight) )
+            {
+            AKNS_TRACE_INFO2("AknsUtils::SBAIB Found (exact) MBM appicon for %x %x", aAppIconIID.iMinor, aAppIconIID.iMajor );
+            indexFound = i;
+            // Do not break, (0,0) might still be there
+            }
+        else if( (sizeArray[i].iWidth==0) &&
+            (sizeArray[i].iHeight==0) )
+            {
+            AKNS_TRACE_INFO2("AknsUtils::SBAIB Using SVG appicon for %x %x", aAppIconIID.iMinor, aAppIconIID.iMajor );
+            indexFound = i;
+            break;
+            }
+        }
+
+    if( indexFound>-1 )
+        {
+        iid.Set( iconData->ImageIID( indexFound ) );
+        sizeArray.Reset();
+        delete iconData;
+        return iid;
+        }
+
+    // Then the largest of smaller or (in terms of one dimension) equal icons
+    TInt bestDSum = 0;
+    TInt dSum;
+    for( i=0; i<numberOfIcons; i++ )
+        {
+        if( (sizeArray[i].iWidth<=aSize.iWidth) &&
+            (sizeArray[i].iHeight<=aSize.iHeight) )
+            {
+            dSum = sizeArray[i].iWidth + sizeArray[i].iHeight;
+            if( dSum > bestDSum )
+                {
+                indexFound = i;
+                bestDSum = dSum;
+                }
+            }
+        }
+
+    if( indexFound>-1 )
+        {
+        iid.Set( iconData->ImageIID( indexFound ) );
+        sizeArray.Reset();
+        delete iconData;
+        return iid;
+        }
+
+    // Finally, the smallest absolute difference
+    bestDSum = KMaxTInt;
+    for( i=0; i<numberOfIcons; i++ )
+        {
+        dSum = ( sizeArray[i].iWidth * sizeArray[i].iHeight ) -
+            (aSize.iWidth*aSize.iHeight);
+        if( dSum < 0 )
+            {
+            dSum = 0-dSum;
+            }
+        if( dSum < bestDSum )
+            {
+            indexFound = i;
+            bestDSum = dSum;
+            }
+        }
+
+    if( indexFound>-1 )
+        {
+        iid.Set( iconData->ImageIID( indexFound ) );
+        }
+
+    sizeArray.Reset();
+    delete iconData;
+
+    if( indexFound<0 )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    return iid;
+    }
+
+//  End of File