uigraphics/AknIcon/src/AknIconLoader.cpp
changeset 0 05e9090e2422
child 50 c6286dcf6040
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uigraphics/AknIcon/src/AknIconLoader.cpp	Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,445 @@
+/*
+* Copyright (c) 2002 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:  Icon loading from MIF files.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <gdi.h>
+#include "AknIconLoader.h"
+#include "AknIconLocationInfo.h"
+#include <mifconvdefs.h>
+
+// CONSTANTS
+
+// ============================ GLOBAL FUNCTIONS ===============================
+
+GLDEF_C void CleanupFreeIcon( TAny* aObj )
+    {
+    static_cast<CAknIconLoader*>( aObj )->FreeIcon();
+    }
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::CAknIconLoader
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CAknIconLoader::CAknIconLoader() : iIconId( -1 )
+    {
+#ifdef _NGATESTING
+    iConfigIconType = -1;
+#endif
+    }
+
+CAknIconLoader* CAknIconLoader::NewL( RFs& aFs, const TDesC& aFileName )
+    {
+    CAknIconLoader* self = new( ELeave ) CAknIconLoader;
+    CleanupStack::PushL( self );
+    self->ConstructL( aFs, aFileName );
+    CleanupStack::Pop();
+    return self;
+    }
+
+// Opened file handle as parameter.
+CAknIconLoader* CAknIconLoader::NewL( RFile& aFile )
+    {
+    CAknIconLoader* self = new( ELeave ) CAknIconLoader;
+    CleanupStack::PushL( self );
+    self->ConstructL( aFile );
+    CleanupStack::Pop();
+    return self;    
+    }
+
+void CAknIconLoader::ConstructL( RFs& aFs, const TDesC& aFileName )
+    {
+    OpenFileL( aFs, aFileName );
+    }
+
+void CAknIconLoader::ConstructL( RFile& aFile )
+    {
+    OpenFileL( aFile );
+    }
+
+// Destructor
+CAknIconLoader::~CAknIconLoader()
+    {
+    iFile.Close();
+    delete iOffsets;
+    delete iSharedOffsets;
+    delete iIcon;
+    delete iCdlEngine;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::OpenFileL
+// -----------------------------------------------------------------------------
+//  
+void CAknIconLoader::OpenFileL( RFs& aFs, const TDesC& aFileName )
+    {
+    iFile.Close();
+    User::LeaveIfError( iFile.Open( aFs, aFileName, EFileRead|EFileShareReadersOnly ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::OpenFileL
+// -----------------------------------------------------------------------------
+//
+void CAknIconLoader::OpenFileL( RFile& aFile )
+    {
+    iFile.Close();
+    User::LeaveIfError( iFile.Duplicate( aFile ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::CloseFile
+// -----------------------------------------------------------------------------
+//
+void CAknIconLoader::CloseFile()
+    {
+    iFile.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::FileHeaderStructL
+// -----------------------------------------------------------------------------
+//  
+void CAknIconLoader::LoadFileHeaderStructL()
+    {
+    if ( !iHeader.iV1.iUid )
+        {
+        TPckg<TMifFileHeaderV1> v1(iHeader.iV1);
+        User::LeaveIfError( iFile.Read( 0, v1, sizeof( TMifFileHeaderV1 ) ) );
+        
+        if (iHeader.iV1.iVersion >= 3)
+            {
+            TPckg<TMifFileHeaderV3> v3(iHeader.iV3);
+            User::LeaveIfError( iFile.Read( v3, sizeof( TMifFileHeaderV3 ) ) );        
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::CheckFileL
+// -----------------------------------------------------------------------------
+//  
+void CAknIconLoader::CheckFileL()
+    {
+    LoadFileHeaderStructL();
+
+    if ( iHeader.iV1.iUid != KUidAvkonMultiIconFile ||
+         iHeader.iV1.iVersion < KMifFirstSupportedVersion || 
+         iHeader.iV1.iVersion > KMifLastSupportedVersion )
+        {
+        #ifdef _DEBUG
+        RDebug::Print(_L("AknIconLoader: Icon file corrupt; file format error!"));
+        #endif
+
+        User::Leave( KErrCorrupt );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::LoadSharedOffsetsL
+// -----------------------------------------------------------------------------
+//  
+void CAknIconLoader::LoadSharedOffsetsL()
+    {
+    if (!CdlEngine::IsCdlEngineCreated())
+        iCdlEngine = CdlEngine::CreateCdlEngineL();
+
+    TBuf<12> dllName;
+    _LIT(KDllNameFormat,"%08x.DLL");
+    dllName.Format(KDllNameFormat, iHeader.iV3.iIndexDllUid);
+    iSharedOffsets = MifHeader::CInstance::NewL(dllName, 0);    // MifHeader DLLs only ever have one instance, and that has id 0
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::LoadOffsetsFromMifL
+// -----------------------------------------------------------------------------
+//  
+void CAknIconLoader::LoadOffsetsFromMifL()
+    {
+    TInt pos = iHeader.iV1.iArrayOffset;
+    TInt length = iHeader.iV1.iArrayLength;
+    HBufC8* offsets = HBufC8::NewL( sizeof( TMifBitmapOffsetElement ) * length );
+    CleanupStack::PushL( offsets );
+    TPtr8 ptr = offsets->Des();
+    
+    User::LeaveIfError( iFile.Read( 
+        pos, ptr, sizeof( TMifBitmapOffsetElement ) * length ) );
+
+    if ( TUint( ptr.Length() ) != sizeof( TMifBitmapOffsetElement ) * length )
+        {
+        #ifdef _DEBUG
+        RDebug::Print(_L("AknIconLoader: Icon file corrupt; EOF at offsets!"));
+        #endif
+
+        User::Leave( KErrCorrupt );
+        }
+
+    CleanupStack::Pop(); // offsets
+    iOffsets = offsets;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::BitmapOffsetsL
+// -----------------------------------------------------------------------------
+//  
+const TMifBitmapOffsetElement* CAknIconLoader::BitmapOffsetsL()
+    {
+    if ( !iOffsets && !iSharedOffsets )
+        {
+        CheckFileL();
+
+        LoadFileHeaderStructL();
+        if (iHeader.iV1.iVersion == 3)
+            LoadSharedOffsetsL();
+        else
+            LoadOffsetsFromMifL();
+        }
+
+    if (iOffsets)
+        return (TMifBitmapOffsetElement*)iOffsets->Ptr();
+    else
+        return &iSharedOffsets->indicies()[0];
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::BitmapOffsetsArrayL
+// -----------------------------------------------------------------------------
+//  
+const TMifBitmapOffsetElement* CAknIconLoader::BitmapOffsetsArrayL()
+    {
+    return BitmapOffsetsL();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::IconWithHeaderL
+// -----------------------------------------------------------------------------
+//  
+TPtrC8 CAknIconLoader::IconWithHeaderL( TInt aId )
+    {
+    if ( iIconId == aId )
+        {
+        return iIcon->Des();
+        }
+
+    LoadFileHeaderStructL();
+
+    TInt usedId = iHeader.iV1.iVersion == 1 ? aId / 2 : aId;
+
+    if ( usedId < 0 || usedId >= iHeader.iV1.iArrayLength )
+        {
+        #ifdef _DEBUG
+        RDebug::Print(_L("AknIconLoader: Icon ID not found!"));
+        #endif
+
+        // Consistent error code with MBM loading.
+        User::Leave( KErrEof );
+        }
+
+    const TMifBitmapOffsetElement* ptr = BitmapOffsetsArrayL();
+    TUint32 offset = ptr[usedId].iOffset;
+    if (((TInt32)offset) < 0)
+        {
+        #ifdef _DEBUG
+        RDebug::Print(_L("AknIconLoader: Icon file corrupt; Negative offset!"));
+        #endif
+        User::Leave( KErrCorrupt );
+        }
+    
+    TUint32 length = ptr[usedId].iLength;
+
+    delete iIcon;
+    iIcon = NULL;
+    iIcon = HBufC8::NewL( length );
+
+    TPtr8 ptr2 = iIcon->Des();
+    User::LeaveIfError( iFile.Read( offset, ptr2, length ) );
+
+    if ( TUint( ptr2.Length() ) != length )
+        {
+        #ifdef _DEBUG
+        RDebug::Print(_L("AknIconLoader: Icon file corrupt; EOF at icon!"));
+        #endif
+
+        User::Leave( KErrCorrupt );
+        }
+
+    iIconId = aId;
+    return iIcon->Des();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::CheckIconL
+// -----------------------------------------------------------------------------
+//  
+void CAknIconLoader::CheckIconL( TInt aId )
+    {
+    TMifIconHeader* header = (TMifIconHeader*)IconWithHeaderL( aId ).Ptr();
+
+    if ( header->iUid != KUidAvkonMultiIcon ||
+         header->iVersion < KMifIconFirstSupportedVersion ||
+         header->iVersion > KMifIconLastSupportedVersion )
+        {
+        #ifdef _DEBUG
+        RDebug::Print(_L("AknIconLoader: Icon file corrupt; icon format error!"));
+        #endif
+        
+        User::Leave( KErrCorrupt );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::IconHeaderL
+// -----------------------------------------------------------------------------
+//  
+TMifIconHeader* CAknIconLoader::IconHeaderL( TInt aId )
+    {
+    CheckIconL( aId );
+
+    TPtrC8 icon = IconWithHeaderL( aId );
+    return (TMifIconHeader*)icon.Ptr();
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::IconL
+// -----------------------------------------------------------------------------
+//  
+TPtrC8 CAknIconLoader::IconL( TInt aId )
+    {
+    CheckIconL( aId );
+
+    TPtrC8 icon = IconWithHeaderL( aId );
+    TMifIconHeader* header = IconHeaderL( aId );
+    icon.Set( icon.Mid( header->iDataOffset, header->iDataLength ) ); 
+    return icon;
+    }
+#ifdef _NGATESTING
+void CAknIconLoader::SetIconTypeConfig(TInt32 aConfigIconType, const TDesC & aNGATestDirectory)
+    {
+    iConfigIconType = aConfigIconType;
+    iNGADirectory.Copy(aNGATestDirectory);
+    }
+
+TInt32 CAknIconLoader::GetDerivedIconTypeL(TInt32 aType, const TDesC & aMifFileName)
+    {
+    if (aType != EIconFormatBMP &&
+        aType != EIconFormatNVG)
+        {
+        if (iConfigIconType != -1)
+            {
+            aType = iConfigIconType;
+            }
+
+        if (aType != EIconFormatNGA)
+            {
+            TInt NGADirectoryLength = iNGADirectory.Length();
+            if ( NGADirectoryLength > 0 && 
+                 NGADirectoryLength < aMifFileName.Length() && 
+                 aMifFileName.Left(NGADirectoryLength).CompareF(iNGADirectory) == 0 )
+                {
+                aType = EIconFormatNGA;
+                }
+            }
+        }
+    
+    return aType;
+    }
+#endif
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::IconTypeL
+// -----------------------------------------------------------------------------
+//  
+TInt32 CAknIconLoader::IconTypeL( TInt aId )
+    {
+    TMifIconHeader* header = IconHeaderL( aId );
+    return header->iType;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::IconDepthL
+// -----------------------------------------------------------------------------
+//  
+TInt32 CAknIconLoader::IconDepthL( TInt aId )
+    {
+    TMifIconHeader* header = IconHeaderL( aId );
+    return header->iDepth; 
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::MaskDepthL
+// -----------------------------------------------------------------------------
+//  
+TInt32 CAknIconLoader::MaskDepthL( TInt aId )
+    {
+    TMifIconHeader* header = IconHeaderL( aId );
+    return header->iMaskDepth; 
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::IconAnimatedL
+// -----------------------------------------------------------------------------
+//  
+TInt32 CAknIconLoader::IconAnimatedL( TInt aId )
+    {
+    TMifIconHeader* header = IconHeaderL( aId );
+    return header->iAnimated;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::FreeIcon
+// -----------------------------------------------------------------------------
+//  
+void CAknIconLoader::FreeIcon()
+    {
+    iIconId = -1;
+    delete iIcon;
+    iIcon = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIconLoader::LoadIconLocationInfoL
+// -----------------------------------------------------------------------------
+//  
+CAknIconLocationInfo* CAknIconLoader::LoadIconLocationInfoL(
+    const TDesC& aFileName )
+    {
+    CheckFileL();
+    
+    // First check whether this is v1 or v2 MIF file.
+    LoadFileHeaderStructL();
+
+    if ( iHeader.iV1.iVersion == 1 )
+        {
+        // V1, no location info array as parameter.        
+        return CAknIconLocationInfo::NewL( aFileName );
+        }
+
+    // V2+ MIF file, load the location info array.
+    BitmapOffsetsL();
+    if (iOffsets)
+        return CAknIconLocationInfo::NewL( aFileName, *iOffsets );
+    else
+        return CAknIconLocationInfo::NewL( aFileName, *iSharedOffsets );
+    }
+
+//  End of File