--- /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