javamanager/javainstaller/installer/src.s60/iconconverter/iconconverter.cpp
changeset 21 2a9601315dfc
child 50 023eef975703
child 60 6c158198356e
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2008-2009 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:  Java Installer component iconconverter.
       
    15 *                Reads icon and .jar file and stores it a temp file in a
       
    16 *                format that can be shown by the S60 UI shell.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 #include <zipfile.h>
       
    22 #include <time.h>
       
    23 
       
    24 #include "javacommonutils.h"
       
    25 #include "logger.h"
       
    26 #include "mifconverter.h"
       
    27 #include "iconconverter.h"
       
    28 
       
    29 namespace java
       
    30 {
       
    31 
       
    32 /**
       
    33  * The icon in S60 temporary drive
       
    34  */
       
    35 _LIT(KTempIconName, "D:\\micon.mbm");
       
    36 
       
    37 /**
       
    38  * The mask in S60 temporary drive
       
    39  */
       
    40 _LIT(KTempMaskName, "D:\\mmask.mbm");
       
    41 
       
    42 
       
    43 // MIF file constants
       
    44 const TInt KMifFileHeaderUid = 0x34232342;
       
    45 const TInt KMifFileHeaderVersion = 2;
       
    46 const TInt KMifFileHeaderLength = 2;
       
    47 
       
    48 const TInt KMifIconHeaderUid = 0x34232343;
       
    49 const TInt KMifIconHeaderVersion = 1;
       
    50 const TInt KMifIconHeaderType = 1;
       
    51 const TInt KMifIconHeaderAnimated = 0;
       
    52 
       
    53 
       
    54 
       
    55 CIconConverter* CIconConverter::NewL(RFs& aRFs)
       
    56 {
       
    57     return new(ELeave) CIconConverter(aRFs);
       
    58 }
       
    59 
       
    60 
       
    61 CIconConverter::CIconConverter(RFs &aRFs)
       
    62 {
       
    63     iRFs = aRFs;
       
    64     iImageDecoder = NULL;
       
    65 
       
    66     iBitmap = NULL;
       
    67     iBitmapMask = NULL;
       
    68 
       
    69     // In case there is no UI on the device ( as when installing an app or
       
    70     // MIDlet suite from PC ) make sure there is an instance of FBS running
       
    71     RFbsSession::Connect();
       
    72 
       
    73     iActiveListener = NULL;
       
    74 }
       
    75 
       
    76 
       
    77 CIconConverter::~CIconConverter()
       
    78 {
       
    79     // Do NOT close file server session
       
    80     delete iBitmapMask;
       
    81     delete iBitmap;
       
    82     delete iImageDecoder;
       
    83 
       
    84     RFbsSession::Disconnect();
       
    85 
       
    86     delete iActiveListener;
       
    87 }
       
    88 
       
    89 
       
    90 int CIconConverter::Convert(
       
    91     const TDesC &aJarFile,
       
    92     const TDesC &aIconFile,
       
    93     const TDesC &aOutputFile,
       
    94     TBool *apWasMbm)
       
    95 {
       
    96     int ret = 0;
       
    97 
       
    98     CActiveScheduler* pScheduler = NULL;
       
    99 
       
   100     if (NULL == CActiveScheduler::Current())
       
   101     {
       
   102         // Must create active scheduler for this JNI thread
       
   103         // to be able to make asynchronous calls
       
   104         pScheduler = new CActiveScheduler();
       
   105         CActiveScheduler::Install(pScheduler);
       
   106     }
       
   107 
       
   108     TRAPD(err, ret = ConvertL(aJarFile, aIconFile, aOutputFile, apWasMbm));
       
   109 
       
   110     delete pScheduler;
       
   111 
       
   112     if (KErrNone != err)
       
   113     {
       
   114         return err;
       
   115     }
       
   116 
       
   117     return ret;
       
   118 }
       
   119 
       
   120 int CIconConverter::ConvertL(
       
   121     const TDesC &aJarFile,
       
   122     const TDesC &aIconFile,
       
   123     const TDesC &aOutputFile,
       
   124     TBool *apWasMbm)
       
   125 {
       
   126     // open jar file
       
   127     CZipFile *pZipFile = CZipFile::NewL(iRFs, aJarFile);
       
   128     CleanupStack::PushL(pZipFile);
       
   129 
       
   130     // try to open the icon inside the jar file
       
   131     CZipFileMember *pZipMember = NULL;
       
   132     // Does the icon name start with '/'
       
   133     if (aIconFile.Locate('/') == 0)
       
   134     {
       
   135         // remove the leading '/' character
       
   136         TFileName tempName = aIconFile.Right(aIconFile.Length() - 1);
       
   137         pZipMember = pZipFile->MemberL(tempName);
       
   138     }
       
   139     else
       
   140     {
       
   141         pZipMember = pZipFile->MemberL(aIconFile);
       
   142     }
       
   143 
       
   144     if (NULL == pZipMember)
       
   145     {
       
   146         LOG(EJavaInstaller, EInfo, "Cannot find icon inside .jar file");
       
   147         User::Leave(KErrNotFound);
       
   148     }
       
   149     CleanupStack::PushL(pZipMember);
       
   150 
       
   151     // reserve buffer for uncompressed icon
       
   152     TUint32 iconSize = pZipMember->UncompressedSize();
       
   153     HBufC8* pIconBuf = HBufC8::NewL(iconSize);
       
   154     CleanupStack::PushL(pIconBuf);
       
   155     TPtr8 ptrIconBuf(NULL, 0);
       
   156     ptrIconBuf.Set(pIconBuf->Des());
       
   157 
       
   158     RZipFileMemberReaderStream *pReader = NULL;
       
   159     User::LeaveIfError(pZipFile->GetInputStreamL(pZipMember, pReader));
       
   160     CleanupStack::PushL(pReader);
       
   161 
       
   162     // read icon to buffer
       
   163     User::LeaveIfError(pReader->Read(ptrIconBuf, iconSize));
       
   164     CleanupStack::PopAndDestroy(pReader);
       
   165 
       
   166     // free unnecessary objects
       
   167     CleanupStack::Pop(pIconBuf); // this is still needed
       
   168     CleanupStack::PopAndDestroy(pZipMember);
       
   169     CleanupStack::PopAndDestroy(pZipFile);
       
   170 
       
   171     CleanupStack::PushL(pIconBuf);
       
   172 
       
   173     // Icon buffer contains SVG icon if the content of the buffer
       
   174     // starts with _L8("<?xml")
       
   175     if ((iconSize > 5) &&
       
   176             (ptrIconBuf[0] == 0x3c) &&
       
   177             (ptrIconBuf[1] == 0x3f) &&
       
   178             (ptrIconBuf[2] == 0x78) &&
       
   179             (ptrIconBuf[3] == 0x6d) &&
       
   180             (ptrIconBuf[4] == 0x6c))
       
   181     {
       
   182         *apWasMbm = EFalse;
       
   183         return ConvertScalableIconL(pIconBuf, aOutputFile);
       
   184     }
       
   185     else
       
   186     {
       
   187         *apWasMbm = ETrue;
       
   188         return ConvertNormalIconL(pIconBuf, ptrIconBuf, aOutputFile);
       
   189     }
       
   190 }
       
   191 
       
   192 int CIconConverter::ConvertNormalIconL(
       
   193     HBufC8* apIconBuf,
       
   194     TPtr8& aptrIconBuf,
       
   195     const TDesC &aOutputFile)
       
   196 {
       
   197     // convert icon in buffer to bitmap
       
   198     if (NULL == iImageDecoder)
       
   199     {
       
   200         // create image decoder if not yet created
       
   201         iImageDecoder = CBufferedImageDecoder::NewL(iRFs);
       
   202     }
       
   203 
       
   204     // Try to create a decoder implementation for the image in the buffer
       
   205     TRAPD(err, iImageDecoder->OpenL(aptrIconBuf));
       
   206     if (KErrNotFound == err)
       
   207     {
       
   208         // If the format is unrecognised AND the first 2 bytes are 0 then
       
   209         // we assume it is a WBMP.
       
   210         // The first two bytes of other formats (e.g. ico) may also begin with 0, 0
       
   211         // but they should have already been recognised by the first call to OpenL.
       
   212         if (((*apIconBuf)[0] == 0) && ((*apIconBuf)[1] == 0))
       
   213         {
       
   214             delete iImageDecoder;
       
   215             iImageDecoder = NULL;
       
   216             iImageDecoder = CBufferedImageDecoder::NewL(iRFs);
       
   217             WLOG(EJavaInstaller, "CIconConverter::ConvertNormalIconL - Format "
       
   218                  "can't be fully identified, assuming this is WBMP");
       
   219             _LIT8(KWBMPMimeType, "image/vnd.wap.wbmp");
       
   220             iImageDecoder->OpenL(aptrIconBuf, KWBMPMimeType);
       
   221             err = KErrNone;
       
   222         }
       
   223     }
       
   224     // Leave if we could not recover from error
       
   225     User::LeaveIfError(err);
       
   226 
       
   227     // get info concerning the icon
       
   228     TFrameInfo frameInfo = iImageDecoder->FrameInfo(0);
       
   229 
       
   230     // create bitmap for icon
       
   231     iBitmap = new(ELeave) CFbsBitmap;
       
   232     User::LeaveIfError(iBitmap->Create(frameInfo.iOverallSizeInPixels, EColor16M));
       
   233 
       
   234     // create bitmap for mask
       
   235     iBitmapMask = new(ELeave) CFbsBitmap;
       
   236     User::LeaveIfError(iBitmapMask->Create(frameInfo.iOverallSizeInPixels, EGray256));
       
   237 
       
   238     // Convert icon to bitmap and possible mask.
       
   239     // Wait until the asynch conversion has been done.
       
   240     iActiveListener = new(ELeave) CActiveListener();
       
   241     iActiveListener->InitialiseActiveListener();
       
   242 
       
   243     // Note that this does not generate mask if the image does not contain it
       
   244     iImageDecoder->Convert(&(iActiveListener->iStatus),
       
   245                            *iBitmap,
       
   246                            *iBitmapMask);
       
   247 
       
   248     CActiveScheduler::Start();
       
   249     err = iActiveListener->iStatus.Int();
       
   250     delete iActiveListener;
       
   251     iActiveListener = NULL;
       
   252     if (err != KErrNone)
       
   253     {
       
   254         User::Leave(err);
       
   255     }
       
   256 
       
   257     // store bitmap to two temp files
       
   258     User::LeaveIfError(iBitmap->Save(KTempIconName));
       
   259     User::LeaveIfError(iBitmapMask->Save(KTempMaskName));
       
   260 
       
   261     // construct multi bitmap file from bitmap and mask files (2 files)
       
   262     TInt32 sourceIds[] = {0, 0};
       
   263     TFileName** filenames = new(ELeave) TFileName*[2];
       
   264     CleanupStack::PushL(filenames);
       
   265     filenames[0] = new(ELeave) TFileName(KTempIconName);
       
   266     CleanupStack::PushL(filenames[0]);
       
   267     filenames[1] = new(ELeave) TFileName(KTempMaskName);
       
   268     CleanupStack::PushL(filenames[1]);
       
   269 
       
   270     CFbsBitmap::StoreL(aOutputFile, 2, (const TDesC**)filenames, sourceIds);
       
   271 
       
   272     // Now try to delete the temp icon and mask files,
       
   273     // ignore possible errors
       
   274     (void)iRFs.Delete(KTempIconName);
       
   275     (void)iRFs.Delete(KTempMaskName);
       
   276 
       
   277     CleanupStack::PopAndDestroy(filenames[1]);
       
   278     CleanupStack::PopAndDestroy(filenames[0]);
       
   279     CleanupStack::PopAndDestroy(filenames);
       
   280     CleanupStack::PopAndDestroy(apIconBuf);
       
   281 
       
   282     return KErrNone;
       
   283 }
       
   284 
       
   285 int CIconConverter::ConvertScalableIconL(
       
   286     HBufC8* apIconBuf,
       
   287     const TDesC &aOutputFile)
       
   288 {
       
   289     TInt iconDataSize = apIconBuf->Length();
       
   290 
       
   291     // File header
       
   292     TMifFileHeader fileHeader;
       
   293     fileHeader.iUid = KMifFileHeaderUid;
       
   294     fileHeader.iVersion = KMifFileHeaderVersion;
       
   295     fileHeader.iOffset = sizeof(fileHeader);
       
   296     fileHeader.iLength = KMifFileHeaderLength;  // number of indexes
       
   297 
       
   298     // Icon offset element
       
   299     TMifIconOffset iconOffset;
       
   300     iconOffset.iIconOffset =
       
   301         sizeof(fileHeader) +
       
   302         sizeof(iconOffset) * KMifFileHeaderLength; // mif header + icon offset
       
   303     iconOffset.iIconLength =
       
   304         sizeof(TMifIconHeader) + iconDataSize; //icon header + icon data
       
   305 
       
   306     // Icon header
       
   307     TMifIconHeader iconHeader;
       
   308     iconHeader.iUid = KMifIconHeaderUid;
       
   309     iconHeader.iVersion = KMifIconHeaderVersion;
       
   310     iconHeader.iOffset = sizeof(iconHeader);  // dataOffset
       
   311     iconHeader.iLength = iconDataSize;  // dataLength
       
   312     iconHeader.iType = KMifIconHeaderType;  // svg
       
   313     iconHeader.iDepth = EColor16M;
       
   314     iconHeader.iAnimated = KMifIconHeaderAnimated;
       
   315     iconHeader.iMaskDepth = EColor16M;
       
   316 
       
   317     // Create MIFConverter class
       
   318     CMifConverter* mifConverter = CMifConverter::NewL(iRFs, aOutputFile);
       
   319     CleanupStack::PushL(mifConverter);
       
   320 
       
   321     // write mif file header
       
   322     mifConverter->WriteMifFileHeaderL(fileHeader);
       
   323     // insert 2 iconOffset elements: first for the image, the other for the mask
       
   324     mifConverter->WriteMifIconOffsetL(iconOffset);
       
   325     mifConverter->WriteMifIconOffsetL(iconOffset);
       
   326     mifConverter->WriteMifIconHeaderL(iconHeader);
       
   327 
       
   328     // write mif file body
       
   329     mifConverter->WriteMifBodyL(apIconBuf);
       
   330 
       
   331     // cleanup
       
   332     CleanupStack::PopAndDestroy(mifConverter);
       
   333     CleanupStack::PopAndDestroy(apIconBuf);
       
   334 
       
   335     return KErrNone;
       
   336 }
       
   337 
       
   338 void CIconConverter:: LogAllSupportedMimeTypes()
       
   339 {
       
   340     // List the file extensions that can be decoded and their corresponding MIME types
       
   341 
       
   342     RFileExtensionMIMETypeArray mimeTypes;
       
   343     CImageDecoder::GetFileTypesL(mimeTypes);
       
   344     TInt nTypes = mimeTypes.Count();
       
   345 
       
   346     for (TInt nInd = 0; nInd < nTypes; nInd++)
       
   347     {
       
   348         const TDesC& extension = mimeTypes[nInd]->FileExtension();
       
   349         // Reserve one char for null terminator
       
   350         HBufC* extBuf = HBufC::NewLC(extension.Length() + 1);
       
   351         TPtr extPtr(extBuf->Des());
       
   352         extPtr.Append(extension);
       
   353         LOG1WSTR(EJavaInstaller, EInfo,
       
   354                  "Icon converter supports file extension %s",
       
   355                  (wchar_t *)(extPtr.PtrZ()));
       
   356         CleanupStack::Pop(extBuf);
       
   357 
       
   358         const TDesC8& mime = mimeTypes[nInd]->MIMEType();
       
   359         HBufC8* mimeBuf = HBufC8::NewLC(mime.Length() + 1);
       
   360         TPtr8 mimePtr(mimeBuf->Des());
       
   361         mimePtr.Append(mime);
       
   362         LOG1(
       
   363             EJavaInstaller,
       
   364             EInfo,
       
   365             "Icon converter supports MIME type %s",
       
   366             mimePtr.PtrZ());
       
   367 
       
   368         CleanupStack::Pop(mimeBuf);
       
   369     }
       
   370 
       
   371     mimeTypes.ResetAndDestroy();
       
   372 }
       
   373 
       
   374 } // namespace java