OpenGTA/read_fnt.cpp

429 lines
13 KiB
C++
Raw Normal View History

2015-12-03 00:37:02 +00:00
/************************************************************************
2015-12-03 00:37:37 +00:00
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
2015-12-03 00:37:02 +00:00
* *
* 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