gfxconversion/mifconv/src/mifconv_bitmapconverter.cpp
author Simon Howkins <simonh@symbian.org>
Wed, 10 Nov 2010 00:18:53 +0000
branchRCL_3
changeset 46 476f0ee3c373
parent 9 1f6339ced17d
permissions -rw-r--r--
Added useful diagnostics that explain why raptor is redefining commands for a target (when processing things through the mifconv.flm). This should make it much easier to pinpoint how the system model should be adjusted to avoid the warnings in future. Also simplified the existing redefinition guards.

/*
* 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 << " ";    
    }