OpenGTA/read_fnt.cpp
Anonymous Maarten e20673c2cd 2007-04-16
2015-12-03 01:37:37 +01:00

429 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/************************************************************************
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
* *
* This file contains code derived from information copyrighted by *
* DMA Design. It may not be used in a commercial product. *
* *
* See license.txt for details. *
* *
* This notice may not be removed or altered. *
************************************************************************/
#include <iostream>
#include <cassert>
#include "cistring.h"
#include "opengta.h"
#include "m_exceptions.h"
#include "log.h"
namespace OpenGTA {
Font::Font(const std::string &file) {
PHYSFS_file *fd = PHYSFS_openRead(file.c_str());
if (fd == NULL) {
std::string f2(file);
transform(f2.begin(), f2.end(), f2.begin(), tolower);
fd = PHYSFS_openRead(f2.c_str());
}
if (!fd)
throw E_FILENOTFOUND(file);
//throw std::string("FileNotFound: ") + file;
readHeader(fd);
int ww = 0;
int lw = 0;
for (uint8_t i = 0; i < numChars; i++) {
Character * ch = new Character(fd, charHeight);
ww += ch->width;
if (ch->width > lw)
lw = ch->width;
chars.push_back(ch);
}
INFO << "total width " << ww << " largest width " << lw << std::endl;
palette.loadFromFile(fd);
PHYSFS_close(fd);
size_t ih = charHeight;
while (ww > 1024) {
ih *= 2;
ww /= 2;
}
workBuffer = new unsigned char[lw*charHeight*4];
loadMapping(file);
}
Font::~Font() {
std::vector<Character*>::iterator i = chars.begin();
while(i != chars.end()) {
delete *i;
i++;
}
chars.clear();
delete [] workBuffer;
}
void Font::readHeader(PHYSFS_file *fd) {
PHYSFS_read(fd, static_cast<void*>(&numChars), 1, 1);
PHYSFS_read(fd, static_cast<void*>(&charHeight), 1, 1);
INFO << "Font contains " << int(numChars) <<
" characters of height " << int(charHeight) << std::endl;
}
void Font::addMapping(char c, size_t num) {
mapping[c] = num;
}
Font::Character* Font::getCharById(size_t num) {
return chars[num];
}
size_t Font::getIdByChar(const char c) {
std::map<char, size_t>::iterator i = mapping.find(c);
if (i == mapping.end())
return 0;
else
return i->second;
}
uint8_t Font::getMoveWidth(const char c) {
std::map<char, size_t>::iterator i = mapping.find(c);
if (i == mapping.end()) {
return chars[0]->width;
}
return chars[i->second]->width;
}
unsigned char* Font::getCharacterBitmap(size_t num, unsigned int *width, unsigned int *height) {
unsigned int len = chars[num]->width;
len *= charHeight;
palette.apply(len, chars[num]->rawData, workBuffer, true);
if (width != NULL)
*width = chars[num]->width;
if (height != NULL)
*height = charHeight;
return workBuffer;
/*
unsigned int glwidth = 1;
unsigned int glheight = 1;
while(glwidth < chars[num]->width)
glwidth <<= 1;
while(glheight < charHeight)
glheight <<= 1;
unsigned char *res = new unsigned char[glwidth*glheight*4];
*/
}
void Font::dumpAs(const char* filename, size_t id) {
unsigned int len = chars[id]->width;
len *= charHeight;
palette.apply(len, chars[id]->rawData, workBuffer, true);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define rmask 0xff000000
#define gmask 0x00ff0000
#define bmask 0x0000ff00
#define amask 0x000000ff
#else
#define rmask 0x000000ff
#define gmask 0x0000ff00
#define bmask 0x00ff0000
#define amask 0xff000000
#endif
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCALPHA,
chars[id]->width, charHeight, 32, rmask, gmask, bmask, amask);
SDL_LockSurface(s);
unsigned char* dst = static_cast<unsigned char*>(s->pixels);
unsigned char * rp = workBuffer;
for (unsigned int i=0; i<len; i++) {
*dst = *rp; ++dst;++rp;
*dst = *rp; ++dst;++rp;
*dst = *rp; ++dst;++rp;
//*dst = 0xff; ++dst;
*dst = *rp; ++dst;++rp;
}
SDL_UnlockSurface(s);
SDL_SaveBMP(s, filename);
SDL_FreeSurface(s);
}
Font::Character::Character(PHYSFS_file *fd, uint8_t height) {
PHYSFS_read(fd, static_cast<void*>(&width), 1, 1);
int c = int(width);
c *= int(height);
//std::cout <<"width " << int(width) << " going to read " << c << " bytes" << std::endl;
rawData = new uint8_t[c];
PHYSFS_read(fd, static_cast<void*>(rawData), 1, c);
}
Font::Character::~Character() {
delete [] rawData;
}
void Font::loadMapping(const std::string & name) {
Util::ci_string name2(name.c_str());
#define chr(n) ((char)(n))
if (name2.find("big1.fon") != std::string::npos) {
INFO << "found mapping: big1.fon - " << name << std::endl;
addMapping('!', 0);
addMapping('-', 12);
for (int j = 65; j < 91; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 192; j < 195; j++) {
addMapping(chr(j), j - 97);
}
addMapping(196, 98);
addMapping(198, 99);
addMapping(199, 100);
for (int j=200; j < 208; j++)
addMapping(j, j - 99);
for (int j=210; j < 213; j++)
addMapping(j, j - 101);
addMapping(214, 112);
for (int j=217; j < 221; j++)
addMapping(j, j - 104);
addMapping(223, 117);
}
else if ((name2.find("pager1.fon") != std::string::npos) ||
(name2.find("pager2.fon") != std::string::npos)) {
addMapping('!', 0);
addMapping('"', 1);
addMapping('$', 3);
addMapping('\'', 6);
addMapping('(', 7);
addMapping(')', 8);
addMapping(',', 11);
addMapping('.', 13);
for (int j = 48; j < 58; j++) {
addMapping(chr(j), j - 33);
}
addMapping(':', 25);
addMapping(';', 26);
addMapping('<', 27);
addMapping('>', 29);
addMapping('?', 30);
addMapping('_', 62);
for (int j = 65; j < 91; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 192; j < 195; j++) {
addMapping(chr(j), j - 97);
}
addMapping(196, 98);
addMapping(198, 99);
addMapping(199, 100);
for (int j=200; j < 208; j++)
addMapping(j, j - 99);
for (int j=210; j < 213; j++)
addMapping(j, j - 101);
addMapping(214, 112);
for (int j=217; j < 221; j++)
addMapping(j, j - 104);
addMapping(223, 117);
}
else if (name2.find("street1.fon") != std::string::npos) {
INFO << "found mapping: street1.fon - " << name << std::endl;
for (int j = 65; j < 91; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 48; j < 58; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 97; j < 123; j++) {
addMapping(chr(j), j - 33);
}
WARN << "incomplete mapping" << std::endl;
}
else if ((name2.find("m_mmiss.fon") != std::string::npos)) {
addMapping('!', 0);
addMapping('"', 1);
addMapping('#', 2);
addMapping('$', 3);
addMapping('\'', 6);
addMapping('(', 7);
addMapping(')', 8);
addMapping('+', 10);
addMapping(',', 11);
addMapping('.', 13);
addMapping('/', 14);
addMapping(':', 25);
addMapping(';', 26);
addMapping('<', 27);
addMapping('=', 28);
addMapping('>', 29);
addMapping('?', 30);
addMapping('\\', 59);
addMapping('[', 58);
addMapping(']', 60);
addMapping('|', 91);
addMapping('~', 93);
for (int j = 65; j < 91; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 97; j < 123; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 48; j < 58; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 192; j < 195; j++) {
addMapping(chr(j), j - 97);
}
// incomplete
}
else if ((name2.find("f_mtext.fon") != std::string::npos)) {
addMapping('!', 0);
addMapping('"', 1);
addMapping('#', 2);
addMapping('$', 3);
addMapping('%', 4);
addMapping('\'', 6);
addMapping('(', 7);
addMapping(')', 8);
addMapping(169, 9); // copyright
addMapping(',', 11);
addMapping('-', 12);
addMapping('.', 13);
addMapping('/', 14);
addMapping(':', 25);
addMapping(';', 26);
addMapping('<', 27);
addMapping('=', 28);
addMapping('>', 29);
addMapping('?', 30);
for (int j = 48; j < 58; j++) {
addMapping(chr(j), j - 33);
}
addMapping('\\', 59);
for (int j = 65; j < 91; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 97; j < 123; j++) {
addMapping(chr(j), j - 33);
}
// incomplete
}
else if ((name2.find("f_mhead.fon") != std::string::npos)) {
addMapping('!', 0);
addMapping('"', 1);
addMapping('#', 2);
addMapping('$', 3);
addMapping('\'', 6);
addMapping('(', 7);
addMapping(')', 8);
addMapping(',', 11);
addMapping('.', 13);
addMapping('/', 14);
addMapping(':', 25);
addMapping(';', 26);
addMapping('<', 27);
addMapping('>', 29);
addMapping('?', 30);
addMapping('\\', 59);
for (int j = 65; j < 91; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 97; j < 123; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 48; j < 58; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 192; j < 195; j++) {
addMapping(chr(j), j - 97);
}
addMapping(196, 98);
addMapping(198, 99);
addMapping(199, 100);
for (int j=200; j < 208; j++)
addMapping(j, j - 99);
for (int j=210; j < 213; j++)
addMapping(j, j - 101);
addMapping(214, 112);
for (int j=217; j < 221; j++)
addMapping(j, j - 104);
addMapping(223, 117);
for (int j=224; j < 227; j++)
addMapping(j, j - 106);
addMapping(228, 121);
for (int j=230; j < 240; j++)
addMapping(j, j - 108);
for (int j=242; j < 245; j++)
addMapping(j, j - 110);
addMapping(246, 135);
for (int j=249; j < 253; j++)
addMapping(j, j - 113);
}
else if ((name2.find("sub1.fon") != std::string::npos) ||
(name2.find("sub2.fon") != std::string::npos)) {
addMapping('!', 0);
addMapping('"', 1);
addMapping('$', 3);
addMapping('\'', 6); // ´
addMapping('(', 7);
addMapping(')', 8);
addMapping(',', 11);
addMapping('-', 12); // not in street1/2
addMapping('.', 13);
addMapping('/', 14);
addMapping(':', 25);
addMapping(';', 26);
addMapping('<', 27);
addMapping('>', 29);
addMapping('?', 30);
for (int j = 65; j < 91; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 97; j < 123; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 48; j < 58; j++) {
addMapping(chr(j), j - 33);
}
for (int j = 192; j < 195; j++) {
addMapping(chr(j), j - 97);
}
addMapping(196, 98);
addMapping(198, 99);
addMapping(199, 100);
for (int j=200; j < 208; j++)
addMapping(j, j - 99);
for (int j=210; j < 213; j++)
addMapping(j, j - 101);
addMapping(214, 112);
for (int j=217; j < 221; j++)
addMapping(j, j - 104);
addMapping(223, 117);
for (int j=224; j < 227; j++)
addMapping(j, j - 106);
addMapping(228, 121);
for (int j=230; j < 240; j++)
addMapping(j, j - 108);
for (int j=242; j < 245; j++)
addMapping(j, j - 110);
addMapping(246, 135);
for (int j=249; j < 253; j++)
addMapping(j, j - 113);
}
else if ((name2.find("score1.fon") != std::string::npos)||
(name2.find("score2.fon") != std::string::npos) ||
(name2.find("score8.fon") != std::string::npos)) {
for (int j = 48; j < 58; j++) {
addMapping(chr(j), j - 48);
}
}
else {
ERROR << "mapping for font " << name << " is not known" << std::endl;
}
}
}
#ifdef FONT_DUMP_TOOL
#include <stdlib.h>
void do_exit() {
PHYSFS_deinit();
}
int main(int argc, char* argv[]) {
PHYSFS_init(argv[0]);
atexit(do_exit);
std::cout << "Physfs-Base: " << PHYSFS_getBaseDir() << std::endl;
PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1);
PHYSFS_addToSearchPath("gtadata.zip", 1);
std::cout << "Has: " << argv[1] << " : " << PHYSFS_exists(argv[1]) << std::endl;
OpenGTA::Font a(argv[1]);
a.dumpAs("out.bmp", atoi(argv[2]));
return 0;
}
#endif