Merge 1. Pull in cpp files in the performance enhanced Khronos RI OVG files which are newly added. I've ignored platform-specific cpp files for linux, macosx, and null operating systems because this local solution has its own platform glue (i.e. facility to target Bitmaps but no full windowing support). I've ignored sfEGLInterface.cpp because this is used as a bridge to go from EGL to Nokia's Platsim which offers an EGL service. That's not relevant to this implementation because this is ARM side code, not Intel side. I just left a comment to sfEGLInterface.cpp in case we need to pick up this later on. The current code compiles on winscw. Prior to this fix, the code works on winscw, and can launch the SVG tiger (tiger.exe). That takes about 20 seconds to render. I hope to always be able to show this icon on each commit, and the plan is for the render time to reduce with this series of submissions. On this commit, the tiger renders ok in 20 seconds.
// Copyright (c) 1997-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:
//
#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
#include <ostream>
#include <iostream>
using namespace std;
#else //!__MSVCDOTNET__ && !__TOOLS2__
#include <ostream.h>
#endif //__MSVCDOTNET__
#include "TOOLSVER.H"
#include "BMCONV.H"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
/**
Returns an informative error message, the result of the program actions performed.
@return Informative error string
@param aErrorNumber The error returned from the actions performed
@param aDestfile The multiple bitmap store file name
@param aDestCreated True if the multiple bitmap store has been created/modified
*/
char* ErrorMessage(int aErrorNumber, char* aDestfile=NULL, bool aDestCreated=false)
{
// Remove the multiple bitmap store if it has been created/modified during an fstream session and there has been an error
if(aDestfile && (aErrorNumber != NoError) && (aDestCreated == true))
{
remove(aDestfile);
}
switch(aErrorNumber)
{
case NoError:
return "Success.";
case NoMemory:
return "Out of memory.";
case Arg:
return "Bad argument.";
case Files:
return "File does not exist";
case SourceFile:
return "Bad source file(s).";
case DestFile:
return "Bad destination file(s).";
case CommandFile:
return "Bad command file.";
case OutOfRange:
return "Number of sources/targets mismatch.";
case TooManyArgs:
return "Too many arguments.";
case UnknownCompression:
return "Unknown source compression type.";
case CompressionError:
return "Compression error.";
case DecompressionError:
return "Decompression error.";
case Bpp:
return "Invalid bitmap mode specified.";
case PaletteFile:
return "Bad palette file.";
case PaletteSupportNotImplemented:
return "Palettes not supported";
case AlphaFiles:
return "Alpha bitmap file does not exist";
case AlphaDimensions:
return "Alpha channel bitmap's dimensions don't match pixel bitmap's dimensions.";
case AlphaBpp:
return "Alpha channel bitmap must be 8bpp.";
default:
return "Unknown error!";
};
}
void Header()
{
cout << "\n";
cout << "\n";
cout << "BMCONV version "<< version << ".\n";
}
void Report(int aError)
{
Header();
cout << ErrorMessage(aError) << "\n";
}
/**
Compiliation information to print to the user at the end of the program.
@param aQuiet Flag if the user selected quiet output mode
@param aError The error returned from the actions performed
@param aType The multiple bitmap store type created
@param aDestfile The multiple bitmap store file name
@param aBitmapFiles The array of bitmaps used
@param aNumFiles The amount of bitmaps used
@param aDestCreated True if the multiple bitmap store has been created/modified
*/
void CompilationReport(int aQuiet,int aError,TStoreType aType,char* aDestfile,char** aBitmapFiles,int aNumFiles, bool aDestCreated)
{
if(!aQuiet || aError)
{
Header();
cout << "Compiling...\n";
if(aType!=ENoStore)
cout << "Multiple bitmap store type: ";
if(aType==EFileStore)
cout << "File store" << "\n";
else if(aType==ERomStore)
cout << "ROM image store" << "\n";
else if(aType==ECompressedRomStore)
cout << "Compressed ROM image store" << "\n";
if(aDestfile!=NULL)
cout << "Epoc file: " << aDestfile << "\n\n";
for(int count=0;count<aNumFiles;count++)
{
cout << "Bitmap file " << count+1 << " : ";
cout << aBitmapFiles[count] << "\n";
}
cout << ErrorMessage(aError, aDestfile, aDestCreated) << "\n";
}
}
void DecompilationReport(int aError,char* aDestfile,char** aBitmapFiles,int aNumFiles)
{
Header();
cout << "Decompiling...\n";
if(aDestfile!=NULL)
cout << "Epoc file: " << aDestfile << "\n\n";
for(int count=0;count<aNumFiles;count++)
{
cout << "Bitmap file " << count+1 << " : ";
cout << aBitmapFiles[count] << "\n";
}
cout << ErrorMessage(aError) << "\n";
}
void Usage()
{
cout << "\n";
cout << "BMCONV version "<< version << ".\n";
cout << "Symbian OS multiple bitmap file/rom store conversion program.\n";
cout << "Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).";
cout << "\n";
cout << "\n";
cout << "Usage:\n";
cout << "BMCONV [-r|-s|-n] [-hfilename] [-q] [-pfilename] epocfile [OPT]bmp_1 ... [OPT]bmp_n\n";
cout << "BMCONV [-r|-s|-n] [-q] [-pfilename] epocfile -mepocfile2\n";
cout << "BMCONV -u epocfile bmp_1 [... bmp_n]\n";
cout << "BMCONV -v epocfile\n";
cout << "BMCONV commandfile\n";
cout << "\n";
cout << " -r specifies a ROM image destination file,\n";
cout << " -s specifies a compressed ROM image file,\n";
cout << " -n disables bitmap File Store compression,\n";
cout << " the default is a compressed File Store file.\n\n";
cout << " -q specifies quiet mode - only errors are reported.\n\n";
cout << " -hfilename specifies the filename for the automatic\n";
cout << " generation of a header file for inclusion into code.\n\n";
cout << " -pfilename gives the filename of a palette file containing 256 hex\n";
cout << " numbers (0x00BBGGRR) specifying the palette for 8bpp colour bitmaps.\n";
cout << " (Omission results in the use of a default palette.)\n\n";
cout << " OPT may be one of -1, -2, -4, -8, -c4, -c8, -c12, -c16, -c24 -c32 -c32a\n";
cout << " specifying bits per pixel and grey-scale-colour, or -mepocfile2\n";
cout << " to specify an existing multiple bitmap file. default is -2.\n\n";
cout << " To avoid ambiguity when specifying -c32 with a bitmap file whose name\n";
cout << " begins with an 'a', use a relative or direct directory reference\n";
cout << " e.g. -c32.\\abitmap.bmp or -c32c:\\abitmap.bmp\n";
cout << " Directory names must not include spaces.\n\n";
cout << " -c32a specifies use of an alpha channel in a 32bpp bitmap. Alpha data\n";
cout << " is supplied in a separate 8bpp bmp file with identical dimensions to\n";
cout << " the pixel data. This file must be named as bmp_n with the suffix '-alpha'\n";
cout << " e.g. if bmp_1 is 'my.bmp' then the file 'my-alpha.bmp' is required in the\n";
cout << " same directory. The alpha file does not need to be specified.\n\n";
cout << " epocfile specifies the epoc multi-bitmap file name.\n";
cout << " bmp_n specifies the nth bitmap file name.\n\n";
cout << " -u decompiles epocfile to bmp_1,...,bmp_n.\n";
cout << " If an alpha channel is present then a further, 8bpp file is output for \n";
cout << " the alpha data, named with an '-alpha' suffix as described above.\n\n";
cout << " -v displays a summary of the bitmaps in epocfile\n";
cout << " otherwise bmp_1,...,bmp_n are compiled to epocfile\n\n";
cout << " commandfile specifies a file containing the commandline\n";
cout << " with commands separated by spaces or newlines.\n\n";
cout << " When bmconv is used on Windows, options may start with '/' or '-'\n";
}
int IsWhiteSpace(char aCharacter)
{
return(aCharacter==' ' || aCharacter=='\n' || aCharacter=='\r' || aCharacter==0x1a);
}
int ProcessCommandFile(char* aCommandFileName,char** aArgPtrs,int& aNumArgs)
{
struct stat fileinfo;
if (stat(aCommandFileName,&fileinfo)==-1)
return CommandFile;
int filesize=fileinfo.st_size;
if (filesize==0)
return NoError;
#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
fstream commandfile(aCommandFileName, ios::in | ios::binary);
#else //!__MSVCDOTNET__
fstream commandfile(aCommandFileName, ios::in | ios::binary | ios::nocreate);
#endif //__MSVCDOTNET__
if(!commandfile.is_open())
return CommandFile;
char* commandData=new char[filesize+1];
if(commandData==NULL)
return NoMemory;
memset(commandData,0,filesize+1);
commandfile.read(commandData,filesize);
commandData[filesize]='\0';
char* commandptr = (char*)commandData;
char* commandptrLimit = (char*)(commandData + filesize);
while (commandptr < commandptrLimit)
{
if(*commandptr=='/' && *(commandptr+1)=='/')
while(*commandptr!='\n' && *commandptr!='\r' && commandptr < commandptrLimit)
*commandptr++=' ';
else if (*commandptr==0x1a)
*commandptr++=' ';
commandptr++;
}
commandptr = (char*)commandData;
while (commandptr < commandptrLimit)
{
while(IsWhiteSpace(*commandptr) && commandptr < commandptrLimit)
*commandptr++='\0';
if (commandptr == commandptrLimit)
break;
aArgPtrs[aNumArgs]=commandptr;
while(!IsWhiteSpace(*commandptr) && commandptr < commandptrLimit)
commandptr++;
if (commandptr == commandptrLimit)
break;
aNumArgs++;
}
commandfile.close();
return NoError;
}
int Decompile(int aArgc,int aNumArgs,char** aArgPtrs)
{
int ret=OutOfRange;
char* destfilename=aArgPtrs[1];
if(aArgc>=4 || aArgc==2)
{
for(int count=2;count<aNumArgs;count++)
{
EpocLoader pl;
ret=pl.LoadEpocBitmap(destfilename,count-2);
if(!ret) ret=pl.SaveBitmap(aArgPtrs[count]);
if(ret) break;
}
DecompilationReport(ret,destfilename,&aArgPtrs[2],aNumArgs-2);
}
else
DecompilationReport(ret,NULL,NULL,0);
return ret;
}
int Compile(int aNumArgs,int aArgArraySize, char** aArgPtrs)
{
TStoreType storeType = EFileStore;
int compression = 1;
int quiet = 0;
char* headerfilename = NULL;
char* palettefilename = NULL;
char* destfilename = NULL;
int ret = OutOfRange;
bool aDestCreated = false;
for(int argnum=0;argnum<aNumArgs;argnum++)
{
if(aArgPtrs[argnum] && (aArgPtrs[argnum][0] == OPTCHAR || aArgPtrs[argnum][0]==ALTERNATE_OPTCHAR))
{
if(aArgPtrs[argnum][1]=='r' || aArgPtrs[argnum][1]=='R')
{
if(storeType==ECompressedRomStore)
{
ret=TooManyArgs;
CompilationReport(quiet,ret,storeType,NULL,NULL,0,aDestCreated);
return ret;
}
storeType=ERomStore;
aArgPtrs[argnum] = NULL;
}
else if(aArgPtrs[argnum][1]=='s' || aArgPtrs[argnum][1]=='S')
{
if(storeType==ERomStore)
{
ret=TooManyArgs;
CompilationReport(quiet,ret,storeType,NULL,NULL,0,aDestCreated);
return ret;
}
storeType=ECompressedRomStore;
aArgPtrs[argnum] = NULL;
}
else if(aArgPtrs[argnum][1]=='n' || aArgPtrs[argnum][1]=='N')
{
compression=0;
aArgPtrs[argnum] = NULL;
}
else if(aArgPtrs[argnum][1]=='h' || aArgPtrs[argnum][1]=='H')
{
headerfilename = &aArgPtrs[argnum][2];
aArgPtrs[argnum] = NULL;
}
else if(aArgPtrs[argnum][1]=='q' || aArgPtrs[argnum][1]=='Q')
{
quiet=1;
aArgPtrs[argnum] = NULL;
}
else if(aArgPtrs[argnum][1]=='p' || aArgPtrs[argnum][1]=='P')
{
palettefilename = &aArgPtrs[argnum][2];
aArgPtrs[argnum] = NULL;
}
}
else
break; // the RNHQP arguments must precede the output filename
}
int firstsource=0;
while(firstsource<aArgArraySize && aArgPtrs[firstsource]==NULL)
firstsource++;
if(firstsource==aArgArraySize) firstsource=0;
destfilename=aArgPtrs[firstsource];
firstsource++;
int numsources=firstsource;
while(numsources<aArgArraySize && aArgPtrs[numsources]!=NULL)
numsources++;
if(numsources==aArgArraySize) numsources=0;
numsources-=firstsource;
if (numsources > 0)
{
BitmapCompiler mp(&aArgPtrs[firstsource],numsources);
ret = mp.Compile(storeType,compression,destfilename,headerfilename,palettefilename);
aDestCreated = true; // The multiple bitmap store has been created/modified
}
CompilationReport(quiet,ret,storeType,destfilename,&aArgPtrs[firstsource],aNumArgs-firstsource,aDestCreated);
return ret;
}
void GetInfo(char* aSourceFile)
{
Header();
EpocLoader pl;
int numSources=-1;
int romFormat=0;
int ret = pl.EpocBitmapCount(aSourceFile, numSources, romFormat);
if (ret)
{
cout << "Problem reading number of bitmaps \n";
cout << ErrorMessage(ret) << "\n";
return;
}
cout << aSourceFile << " is a " << (romFormat? "ROM image":"File store")
<< " containing " << numSources << ((numSources==1)? " bitmap\n":" bitmaps\n");
for (int count = 0;count<numSources;count++)
{
ret = pl.LoadEpocBitmap(aSourceFile,count);
if (ret == OutOfRange)
break;
cout << "\n";
if (ret)
{
cout << "Problem loading bitmap number " << count << "\n";
cout << ErrorMessage(ret) << "\n";
break;
}
else
{
SEpocBitmapHeader h = pl.Header();
cout << "Bitmap " << count + 1 << " information:\n";
cout << "Pixel size " << h.iWidthInPixels << " x " << h.iHeightInPixels << "\n";
cout << "Twips size " << h.iWidthInTwips << " x " << h.iHeightInTwips << "\n";
cout << h.iBitsPerPixel << " Bpp ";
if (h.iColor == EColorBitmap)
cout << "Colour";
else if (h.iColor == EColorBitmapAlpha || h.iColor == EColorBitmapAlphaPM)
cout << "Colour with alpha channel";
else if(h.iColor == EMonochromeBitmap)
cout << "Monochrome";
else
cout << "Unknown colour format";
cout << "\n";
if (h.iPaletteEntries > 0)
cout << "Palette entries " << h.iPaletteEntries;
int byteSize = BitmapUtils::ByteWidth(h.iWidthInPixels,h.iBitsPerPixel) * h.iHeightInPixels;
int compressionRatio = 0;
if (byteSize > 0)
compressionRatio = (h.iBitmapSize - sizeof(SEpocBitmapHeader)) * 100 / byteSize;
switch (h.iCompression)
{
case ENoBitmapCompression:
cout << "No compression\n";
break;
case EByteRLECompression:
cout << "Bytewise RLE compression " << compressionRatio << "%\n";
break;
case ETwelveBitRLECompression:
cout << "12 bit RLE compression " << compressionRatio << "%\n";
break;
case ESixteenBitRLECompression:
cout << "16 bit RLE compression " << compressionRatio << "%\n";
break;
case ETwentyFourBitRLECompression:
cout << "24 bit RLE compression " << compressionRatio << "%\n";
break;
case EThirtyTwoUBitRLECompression:
cout << "unsigned 32 bit RLE compression (no alpha channel) " << compressionRatio << "%\n";
break;
case EThirtyTwoABitRLECompression:
cout << "unsigned 32 bit RLE compression (with alpha channel) " << compressionRatio << "%\n";
break;
// case ERLECompressionLast: // Added to supress unhandled switch warning
default:
break;
}
}
}
cout << "\n";
}
class TAutoPtr
{
public:
TAutoPtr(char** aPtr) :
iPtr(aPtr)
{
}
~TAutoPtr()
{
delete iPtr;
}
private:
char** iPtr;
};
int main(int argc,char* argv[],char* [])
{
if (argc <= 1)
{
Usage();
return 0;
}
int optMaxCnt = argc;
if(argc==2) // The single argument must be a command file name
{
struct stat fileinfo;
if (stat(argv[1],&fileinfo)==-1)
{
Report(CommandFile);
return 0;
}
optMaxCnt = fileinfo.st_size;
}
char** argptrs = new char*[optMaxCnt];
if(!argptrs)
{
Report(NoMemory);
return 0;
}
TAutoPtr autoPtr(argptrs);
memset(argptrs, 0, optMaxCnt * sizeof(char*));
int numargs = 0;
if(argc>2) // Explicit arguments are present
{
for(int count=0;count<argc-1;count++)
argptrs[count]=argv[count+1];
numargs = argc-1;
}
else // The single argument must be a command file name
{
int ret = ProcessCommandFile(argv[1],argptrs,numargs);
if (ret)
{
Report(ret);
return 0;
}
}
if ((argptrs[0]!=NULL && (argptrs[0][0]==OPTCHAR || argptrs[0][0]==ALTERNATE_OPTCHAR)) && (argptrs[0][1]=='u' || argptrs[0][1]=='U')) {
return Decompile(argc,numargs,argptrs); }
if ((argptrs[0]!=NULL && (argptrs[0][0]==OPTCHAR || argptrs[0][0]==ALTERNATE_OPTCHAR)) && (argptrs[0][1]=='v' || argptrs[0][1]=='V'))
{
GetInfo(argptrs[1]);
return 0;
}
return Compile(numargs,optMaxCnt,argptrs);
}