/************************************************************************ * Copyright (c) 2005-2006 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 #include #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::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(&numChars), 1, 1); PHYSFS_read(fd, static_cast(&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::iterator i = mapping.find(c); if (i == mapping.end()) return 0; else return i->second; } uint8_t Font::getMoveWidth(const char c) { std::map::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(s->pixels); unsigned char * rp = workBuffer; for (unsigned int i=0; i(&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(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 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