gfxconversion/mifconv/src/mifconv_bitmapconverter.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 15 Mar 2010 12:42:44 +0200
branchRCL_3
changeset 9 1f6339ced17d
parent 0 f453ebb75370
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:  Mifconv bitmap converters class.
*
*/


#include "mifconv.h"
#include "mifconv_bitmapconverter.h"
#include "mifconv_util.h"
#include "mifconv_exception.h"
#include "mifconv_argumentmanager.h"
#include "mifconv_mbmgenerator.h"
#include "mifconv_mbmgenerator_pbmcomp.h"
#include <stdio.h>
#include <sys/stat.h>

using namespace std;

#ifdef __linux__
const char* DefaultPaletteFileSearchLocations[] =
{
    "/epoc32/include/mw/ThirdPartyBitmap.pal",
    "/epoc32/include/middleware/ThirdPartyBitmap.pal",
    "/epoc32/include/ThirdPartyBitmap.pal"
};
#else
const char* DefaultPaletteFileSearchLocations[] =
{
    "\\epoc32\\include\\mw\\ThirdPartyBitmap.pal",
    "\\epoc32\\include\\middleware\\ThirdPartyBitmap.pal",
    "\\epoc32\\include\\ThirdPartyBitmap.pal"
};
#endif

/**
 *
 */
MifConvBitmapConverter::MifConvBitmapConverter()
{
    MifConvArgumentManager* argMgr = MifConvArgumentManager::Instance();
    // Output file:
    iTargetFilename = MifConvUtil::FilenameWithoutExtension(argMgr->TargetFile()) + "." + MifConvString(MBM_FILE_EXTENSION);
}

/**
 *
 */
MifConvBitmapConverter::~MifConvBitmapConverter()
{
}

/**
 *
 */
void MifConvBitmapConverter::Init()
{
    CleanupTargetFiles();
}

/**
 *
 */
void MifConvBitmapConverter::CleanupTargetFiles()
{
    if( MifConvUtil::FileExists(iTargetFilename) )
    {
        // Try to remove file MIFCONV_MAX_REMOVE_TRIES times, no exception in case of failure:
        MifConvUtil::RemoveFile(iTargetFilename, MIFCONV_MAX_REMOVE_TRIES, true);
    }
}

/**
 *
 */
void MifConvBitmapConverter::AppendFile( const MifConvSourceFile& aSourcefile )
{    
    if( MifConvUtil::FileExtension( aSourcefile.Filename() ) == BMP_FILE_EXTENSION )
    {
        iSourceFiles.push_back( aSourcefile );
    }
}

/**
 *
 */
void MifConvBitmapConverter::Convert()
{
    if( iSourceFiles.size() > 0 )
    {
        ConvertToMbm();
    }
}

/**
 *
 */
void MifConvBitmapConverter::Cleanup(bool err)
{
    CleanupTempFiles();
    if( err )
    {
        CleanupTargetFiles();
    }
}

/**
 *
 */
void MifConvBitmapConverter::ConvertToMbm()
{   
    MifConvArgumentManager* argMgr = MifConvArgumentManager::Instance();
    const MifConvString& bmconvPath = argMgr->StringValue(MifConvBmconvPathArg);
    
    // If bmconv.exe's location is given.
    if( bmconvPath.length() > 0 ) 
    {
        // Create and initialize the temp file.  
        InitTempFile();
    
        // Run external bmconv.
        RunExternalBmconv(bmconvPath);
    }
    else // Use internal logic.
    {
        // Create the path if not existing.
        MifConvUtil::EnsurePathExists(iTargetFilename, true);
        
        cout << "Writing mbm: " << iTargetFilename << endl; 
    
        // Variable for source files.
        MifConvSourceFileList sourceFiles;
        
        // Get palette file name from either arguments or default values.
        MifConvString palettefilename = GetPaletteFileName();
        
        // Add filenames to the temp file.
        // Sourcefiles and their mask files are considered as same.
        for( MifConvSourceFileList::iterator i = iSourceFiles.begin(); i != iSourceFiles.end(); ++i )
            {               
            cout << "Loading file: " << i->Filename() << endl;
            sourceFiles.push_back( *i );              
            // Prepare also for the case that mask is not used at all.
            if (i->BmpMaskFilename().length() > 0 )
                {
                cout << "Loading file: " << i->BmpMaskFilename() << endl;
                MifConvSourceFile maskFile;
                maskFile.SetFilename(i->BmpMaskFilename());
                maskFile.SetDepthString(i->MaskDepthString());
                sourceFiles.push_back( maskFile );
                }
            }
       
        // Create internal bmconv to handle compiling.
        BmConv bmConv = BmConv(sourceFiles);
        int ret = bmConv.Compile(iTargetFilename.c_str(), palettefilename); 
        if (ret) {
            THROW_ERROR_COMMON("BMP to MBM conversion failed", MifConvString(__FILE__), __LINE__);
        }

    }
}

const MifConvString MifConvBitmapConverter::GetPaletteFileName() 
    {
    
    // Get palette argument.
    MifConvArgumentManager* argMgr = MifConvArgumentManager::Instance();
    const MifConvString& paletteArg = argMgr->StringValue(MifConvPaletteFileArg);
    
    MifConvString palettefilename;       
    MifConvString paletteBuf;
    
    // If palette argument has been given.
    if( paletteArg.length() == 0 )
        {
        // Default palette file.
        const MifConvString& defaultPalettefile = DefaultPaletteFileName(paletteBuf);
        
        // Palette file not given in arguments. If the default palette file
        // was found, use it, otherwise throw error.
        if( defaultPalettefile.length() > 0 )
            {
            palettefilename = defaultPalettefile;           
            }
        else
            {
            // Palettefile not given in arguments nor found from default locations:
            THROW_ERROR_COMMON("Unable to open palette file from default locations! ", MifConvString(__FILE__), __LINE__ );
            }
        } else {
        palettefilename = paletteArg;           
        }   
    
    // Check that palette file exists.
    if( !MifConvUtil::FileExists(palettefilename) )
    {
        THROW_ERROR_COMMON("Unable to open palette file! " + paletteArg, MifConvString(__FILE__), __LINE__ );
    }
    
    return palettefilename;
    }

const MifConvString& MifConvBitmapConverter::DefaultPaletteFileName(MifConvString& aBuf)
    {
    int numOfSearchLocations = sizeof(DefaultPaletteFileSearchLocations)/sizeof(char*);
    
    // Get epocroot.
    MifConvString epocRoot(MifConvArgumentManager::Instance()->EpocRoot());
    
    for( int i = 0; i < numOfSearchLocations; ++i )
        {
        aBuf = epocRoot;
        aBuf += DefaultPaletteFileSearchLocations[i];
        
        // Remove possible double-\.
        if ((aBuf.at(1) == '\\') && (aBuf.at(0) == '\\')) aBuf = aBuf.substr(1, aBuf.length()-1);
        if( MifConvUtil::FileExists(aBuf))
            {
            return aBuf;
            }
        }
    aBuf = "";
    return aBuf;
    }

/**
 *
 */
void MifConvBitmapConverter::InitTempFile()
{
    // Take an instance from the argument manager.
    MifConvArgumentManager* argMgr = MifConvArgumentManager::Instance();

    // Construct temp file name.
    iTempDir = MifConvUtil::DefaultTempDirectory();
    
    const MifConvString& tempDirArg = argMgr->StringValue(MifConvTempPathArg);
    if( tempDirArg.length() > 0 )
    {
        iTempDir = tempDirArg;
    }

    if( iTempDir.length() > 0 && iTempDir.at(iTempDir.length()-1) != DIR_SEPARATOR2 )
    {
        iTempDir.append(DIR_SEPARATOR);
    }

    // Generate new temp-filename:
    iTempDir.append(MifConvUtil::TemporaryFilename());

    // append tmp at as postfix
    // this is needed because the generated name can contain a single period '.'
    // character as the last character which is eaten away when the directory created.
    iTempDir.append(MifConvString("tmp"));

    MifConvUtil::EnsurePathExists(iTempDir);

    iTempDir.append(DIR_SEPARATOR);

    iTempFilename = iTempDir + MifConvUtil::FilenameWithoutExtension(MifConvUtil::FilenameWithoutPath(argMgr->TargetFile()));
    iTempFilename += BMCONV_TEMP_FILE_POSTFIX;
    
    // Create temp file
    fstream tempFile(iTempFilename.c_str(), ios::out|ios::binary|ios::trunc);
    if (!tempFile.is_open())
    {        
        throw MifConvException(MifConvString("Unable to create tmp file! ") + iTempFilename);    
    }

    try {
        // quiet mode
        // ex. "-q"
        tempFile << BMCONV_OPTION_PREFIX << BMCONV_QUIET_PARAMETER << " ";
        
        // Palette argument
        const MifConvString& paletteArg = argMgr->StringValue(MifConvPaletteFileArg);
        if( paletteArg.length() > 0 )
        {
            // ex. "-p"
            tempFile << BMCONV_OPTION_PREFIX << BMCONV_PALETTE_PARAMETER;            
            tempFile << MifConvString(paletteArg + " ");
        }

        tempFile << iTargetFilename << " ";
        
        // Add filenames to the temp file
        for( MifConvSourceFileList::iterator i = iSourceFiles.begin(); i != iSourceFiles.end(); ++i )
        {
            AppendBmpToTempFile(tempFile, *i);
        }
    }
    catch(...) {
        tempFile.close();
        throw;
    }    
    tempFile.close();
}

/**
 * Run external bmconv from given path.
 */
void MifConvBitmapConverter::RunExternalBmconv( const MifConvString& aBmconvPath )
{    
    // Build bmconv command    
    MifConvString bmconvCommand("\""); // Open " mark
    
    bmconvCommand += aBmconvPath; // If the path is given, use it.
        
    // Ensure that the last char of the path is dir-separator:
    if( bmconvCommand.length() > 1 && bmconvCommand.at(bmconvCommand.length()-1) != DIR_SEPARATOR2 )
        bmconvCommand += DIR_SEPARATOR;

    // Then add bmconv executable call and close the " mark
    bmconvCommand += BMCONV_EXECUTABLE_NAME + MifConvString("\" ");  
    bmconvCommand += "\"" + iTempFilename + "\"";
            
    MifConvUtil::EnsurePathExists(iTargetFilename, true);
        
    cout << "Writing mbm: " << iTargetFilename << endl;           
    int err = 0;
      
#ifdef __linux__
    if ((err = system (MifConvString(bmconvCommand).c_str())) != 0)   // Returns 0 if success
#else
    if ((err = system (MifConvString("\""+bmconvCommand+"\"").c_str())) != 0)   // Returns 0 if success
#endif
    {
            THROW_ERROR_COMMON("Executing BMCONV failed", MifConvString(__FILE__), __LINE__);
    }
}

/**
 *
 */
void MifConvBitmapConverter::CleanupTempFiles()
{
    if( iTempFilename.length() > 0 && remove( iTempFilename.c_str() ) != 0 )
    {
        perror( "Error deleting temporary file (bitmap conversion)" );
    }
    
    if( iTempDir.length() > 0 && MifConvUtil::RemoveDirectory( iTempDir ) != 0 )
    {
        perror( "Error deleting temporary directory (bitmap conversion)" );
    }
}

/**
 *
 */
void MifConvBitmapConverter::AppendBmpToTempFile(fstream& aStream, const MifConvSourceFile& aBmpFile)
    {
    cout << "Loading file: " << aBmpFile.Filename() << endl;
    
    // ex. "-8..\..\bitmaps\mifconv_test_bitmap_01.bmp"
    aStream << BMCONV_OPTION_PREFIX;
    aStream << aBmpFile.DepthString();
    aStream << aBmpFile.Filename();
    aStream << " ";
        
    // Prepare also for the case that mask is not used at all.
    const MifConvString& maskName = aBmpFile.BmpMaskFilename();
    if (maskName.length() > 0 )
    {
        cout << "Loading file: " << maskName << endl;
        
        // ex. -8..\..\bitmaps\mifconv_test_bitmap_01_mask_soft.bmp 
        aStream << BMCONV_OPTION_PREFIX;
        aStream << aBmpFile.MaskDepthString();
        aStream << maskName;      
    }
    aStream << " ";    
    }