#include "glbase.h" #include "glfont.h" #include "Input.h" Uint8 prescale2[4] = { 0, 85, 170, 255 }, prescale3[8] = { 0, 36, 72, 109, 145, 182, 218, 255 }; /* font file format ================ off|siz|description ---+---+------------------------------- 0 | 2 | Number of entries = nbentries 2 | 1 | Flags 3 | 1 | maxX (maximum width) 4 | 1 | maxY (maximum height) 5 | X | char entries 5+X| Y | char map X = (maxX * maxY + 1) * nbentries Y = nbentries * 4 Flags: ===== 0000000R R = RGBA (=1) or Alpha (=0) RGBA in 1232 format: ABBGGGRR Each entries: ============ off|siz|description ---+---+------------------------------- 0 | 1 | True size of the entry 1 | Z | Datas Z = maxX * maxY Char map: ======== nbentries entries, each entry = 4 bytes = 2 uint16 off|siz|description ---+---+------------------------------- 0 | 2 | Unicode (?) 2 | 2 | Corresponding char entry I'm not sure about Unicode. I write this only to say it's an attempt to make the fonts "internationals". If the "unicode" is < 255, then it should match only one byte in the string. Otherwise, it should match two bytes. Variables comments ================== nbcU = number of chars on X by texture nbcV = number of chars on Y by texture nbcT = number of char by texture nbT = number of textures */ mogltk::font::font(const String & file) { Input ffont(file); int i; ffont.SetZ(); ffont.read(&nbentries, 2); ffont.read(&flags, 1); ffont.read(&maxX, 1); ffont.read(&maxY, 1); nbcU = 256 / maxX; nbcV = 256 / maxY; nbcT = nbcU * nbcV; nbT = nbentries / nbcT; if (nbentries % nbcT) { nbT++; } fonttex = (texture **) malloc(nbT * sizeof(texture *)); for (i = 0; i < nbT; i++) { fonttex[i] = new texture(256, 256, true); } sizes = (Uint8 *) malloc(nbentries * sizeof(Uint8)); Uint8 * curtex = (Uint8 *) fonttex[0]->GetSurface()->pixels; Uint8 curU = 0, curV = 0, curT = 0; for (int i = 0; i < nbentries; i++) { ffont.read(&sizes[i], 1); for (int v = 0; v < maxY; v++) { for (int u = 0; u < maxX; u++) { Uint8 f; ffont.read(&f, 1); if (flags & 1) { Uint8 r, g, b, a; r = f & 3; g = (f >> 2) & 7; b = (f >> 5) & 3; a = (f >> 7) & 1; curtex[(curU + u + (curV + v) * 256) * 4 + 0] = prescale2[r]; curtex[(curU + u + (curV + v) * 256) * 4 + 1] = prescale3[g]; curtex[(curU + u + (curV + v) * 256) * 4 + 2] = prescale2[b]; curtex[(curU + u + (curV + v) * 256) * 4 + 3] = a ? 255 : 0; } else { curtex[(curU + u + (curV + v) * 256) * 4 + 0] = 255; curtex[(curU + u + (curV + v) * 256) * 4 + 1] = 255; curtex[(curU + u + (curV + v) * 256) * 4 + 2] = 255; curtex[(curU + u + (curV + v) * 256) * 4 + 3] = f; } } } if ((curU += maxX) >= 256) { curU = 0; if ((curV += maxY) >= 256) { curV = 0; curtex = (Uint8 *) fonttex[++curT]->GetSurface()->pixels; } } } for (int i = 0; i < nbT; i++) { fonttex[i]->Generate(); } corresp = (Uint16 *) malloc(nbentries * 2 * sizeof(Uint16)); ffont.read(corresp, 2 * sizeof(Uint16) * nbentries); } mogltk::font::~font() { int i; for (i = 0; i < nbT; i++) { delete fonttex[i]; } free((void *) fonttex); free(sizes); } void mogltk::font::drawentry(Uint16 entry, Color c, int x, int y) { bool was2D; was2D = mogltk::glbase::is2D(); if (!was2D) { mogltk::glbase::Enter2DMode(); } if (!was2D) { mogltk::glbase::Leave2DMode(); } }