gfxconversion/mifconv/src/mifconv_mifconverter.cpp
author Simon Howkins <simonh@symbian.org>
Wed, 10 Nov 2010 00:18:53 +0000
branchRCL_3
changeset 46 476f0ee3c373
parent 0 f453ebb75370
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 MIF converters class.
*
*/


#include "mifconv.h"
#include "mifconv_mifconverter.h"
#include "mifconv_util.h"
#include "mifconv_exception.h"
#include "mifconv_argumentmanager.h"

// File versions:
// V1 - first version.
// V2 - stores information if icon location (MIF/MBM) inside the MIF file (bitmap offsets array).
// This way, icon IDs in MBG header can be always the same regardless of which icons are in MIF
// file and which in MBM file.
static const int KFileVersion(2);
static const int KIconVersion(1);

static const int FileHeaderSizeInBytes = 4*4;
static const int IconHeaderSizeInBytes = 4*8;
static const int KUidAvkonMultiIconFile(0x034232342);
static const int KUidAvkonMultiIcon(0x034232343);

//static const int IconFormatType_BMP(0);
//static const int IconFormatType_SVG(1);

static const unsigned int svgbSignatureLow (0x03FA56CC); //66737868
static const unsigned int svgbSignatureHigh(0x03FA56CF); //66737871

static const unsigned int nvgSignatureLow (0x0067766E); //('n'+'v'+'g'+0)
static const unsigned int nvgSignatureHigh(0xFF67766E); //('n'+'v'+'g'+255)

/**
 *
 */
MifConvMifConverter::MifConvMifConverter()
{
    MifConvArgumentManager* argMgr = MifConvArgumentManager::Instance();
    iTargetFilename = argMgr->TargetFile();
}

/**
 *
 */
MifConvMifConverter::~MifConvMifConverter()
{
    // Delete file contents
    for( StringPtrVector::iterator i = iContentPointers.begin(); i != iContentPointers.end(); ++i )
    {
        delete[] *i;
    }
}

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

/**
 *
 */
void MifConvMifConverter::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 MifConvMifConverter::AppendFile( const MifConvSourceFile& sourcefile )
{     
	if( MifConvUtil::FileExtension( sourcefile.Filename() ) == BMP_FILE_EXTENSION ||
        MifConvUtil::FileExtension( sourcefile.Filename() ) == SVG_FILE_EXTENSION ||
        MifConvUtil::FileExtension( sourcefile.Filename() ) == SVGB_BINARY_FILE_EXTENSION )
	{        
		iSourceFiles.push_back( sourcefile );
	}
}

void MifConvMifConverter::Convert()
{
 	ReadFileContents();
    cout << "Writing mif: " << MifConvArgumentManager::Instance()->TargetFile() << endl;
	ConvertToMif();
}

void MifConvMifConverter::ReadFileContents()
{   
    for( MifConvSourceFileList::iterator i = iSourceFiles.begin(); i != iSourceFiles.end(); ++i )
    {        
        // Just read the contents of the .svgb files
        if( MifConvUtil::FileExtension( i->Filename() ) != BMP_FILE_EXTENSION )
        {            
            if( MifConvUtil::FileExists(i->Filename()) == false )
            {
                THROW_ERROR_COMMON("Unable to open file for reading! " + i->Filename(), MifConvString(__FILE__), __LINE__ );
            }            
            cout << "Loading file: " << i->Filename() << endl;
            MifConvFileData retVal = MifConvUtil::FileContents(i->Filename());
            iContentPointers.push_back(retVal.first); // Save pointer for deleting it later
            i->SetContent(retVal.first, retVal.second);
        }
    }
}


void MifConvMifConverter::Cleanup(bool err)
{
	CleanupTempFiles();
	if( err )
	{
	    CleanupTargetFiles();
	}
}

void MifConvMifConverter::ConvertToMif()
{  
    try {
        OpenTargetFile();
    }
    catch( MifConvException& e )
    {
        // If file creation/opening was not successful, give warning and return:
        MifConvString debugStr("WARNING: Target file " + iTargetFilename + " cannot be opened for writing.");
        cout <<  debugStr  << endl;
        MifConvUtil::DebugLog(debugStr);
        return;
    }
    WriteTargetHeader();
    WriteIconArray();
    WriteIcons();
}

void MifConvMifConverter::OpenTargetFile()
{
    iTargetFile.open( iTargetFilename.c_str(), ios::out|ios::binary );

    if (!iTargetFile.is_open())
    {
        // Create path if it does not exist.
        MifConvUtil::EnsurePathExists(iTargetFilename, true);
        iTargetFile.clear();
        iTargetFile.open( iTargetFilename.c_str(), ios::out|ios::binary );
    }
    if (!iTargetFile.is_open())
    {
        THROW_ERROR_COMMON("Cannot write to file! " + iTargetFilename, MifConvString(__FILE__), __LINE__);
    }
}

void MifConvMifConverter::WriteTargetHeader()
    {
    size_t arraySize = iSourceFiles.size() * 2;
    int offset = FileHeaderSizeInBytes;
    iTargetFile.write( (char*) &KUidAvkonMultiIconFile, 4 );
    iTargetFile.write( (char*) &KFileVersion, 4 );
    iTargetFile.write( (char*) &offset, 4 );
    iTargetFile.write( (char*) &arraySize, 4 );
    }

void MifConvMifConverter::CleanupTempFiles()
{
}

void MifConvMifConverter::WriteIcons()
{    
    for( MifConvSourceFileList::iterator i = iSourceFiles.begin(); i != iSourceFiles.end(); ++i )
    {
        if( i->ContentLength() > 0 )
        {
            WriteIconHeader(*i);
            WriteIconData(*i);
        }
    }
}

MifConvDefs::IconFormatType MifConvMifConverter::ReadIconBinaryType(const MifConvSourceFile& src)
{
    MifConvDefs::IconFormatType ret = MifConvDefs::IconFormatType_SVG;
    
    if( src.ContentLength() >= 4 )
    {
        const char* iconData = src.Content();
        
        if( iconData[0] == 'n' &&
            iconData[1] == 'v' &&
            iconData[2] == 'g' )
        {
            ret = MifConvDefs::IconFormatType_NVG;
        }
    }
    
    return ret;
}

void MifConvMifConverter::WriteIconHeader(const MifConvSourceFile& src)
{
    int type = 0;
    if( MifConvUtil::FileExtension(src.Filename()) == BMP_FILE_EXTENSION )
        type = MifConvDefs::IconFormatType_BMP;
    else
        type = ReadIconBinaryType(src);
        //type = IconFormatType_SVG;

    int animated = (int) src.IsAnimated();
    int dataLen = src.ContentLength();
    int depth = src.DisplayMode();
    int mask = src.MaskDisplayMode();
    int dataoffset = IconHeaderSizeInBytes; // 8 = number of writes in this method.

    iTargetFile.write((char*)&KUidAvkonMultiIcon, 4); // 1
    iTargetFile.write((char*)&KIconVersion, 4);       // 2
    iTargetFile.write((char*)&dataoffset, 4);         // 3
    iTargetFile.write((char*)&dataLen, 4);        // 4
    iTargetFile.write((char*)&type, 4);          // 5
    iTargetFile.write((char*)&depth, 4);         // 6
    iTargetFile.write((char*)&animated, 4);      // 7
    iTargetFile.write((char*)&mask, 4);     // 8
}

void MifConvMifConverter::WriteIconData(const MifConvSourceFile& src)
{
    if( src.Content() )
    {        
        iTargetFile.write(src.Content(), src.ContentLength());
    }
}

/**
* 
*/
void MifConvMifConverter::WriteIconArray()
{
    int offset = (int) FileHeaderSizeInBytes +  (int)iSourceFiles.size()*4*2*2;
    MifConvSourceFileList::iterator i = iSourceFiles.begin();

    int mbmIndex = 0;
    int zero = 0;

    for( ; i != iSourceFiles.end(); ++i )
    {
        // MIF icon
        if( MifConvUtil::FileExtension(i->Filename()) != BMP_FILE_EXTENSION )
        {            
            int length = i->ContentLength() + IconHeaderSizeInBytes;
            iTargetFile.write( (char*) &offset, 4 );
            iTargetFile.write( (char*) &length, 4 );
            // same information for the mask...
            iTargetFile.write( (char*) &offset, 4 );
            iTargetFile.write( (char*) &length, 4 );

            offset += length;            
        }
        // MBM icon
        else
        {
            iTargetFile.write( (char*) &mbmIndex, 4 );
            iTargetFile.write( (char*) &zero, 4 );

            // Masked MBM icon -> There is own MBM index for the mask.
            if(i->MaskDepth() != IconMaskDepth_Undefined )
            {
                mbmIndex--;
            }

            iTargetFile.write( (char*) &mbmIndex, 4 );
            iTargetFile.write( (char*) &zero, 4 );

            // MBM incides are coded as negative in the 'offset' field,
            // so that they can be easily separated from the actual MIF offsets.
            mbmIndex--;
        }
    }
}