summaryrefslogtreecommitdiff
path: root/lib/font.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/font.cc')
-rw-r--r--lib/font.cc318
1 files changed, 318 insertions, 0 deletions
diff --git a/lib/font.cc b/lib/font.cc
new file mode 100644
index 0000000..7cc57f6
--- /dev/null
+++ b/lib/font.cc
@@ -0,0 +1,318 @@
+#include <stdarg.h>
+#include "base.h"
+#include "font.h"
+#include "Input.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+Uint8 prescale2[4] = { 0, 85, 170, 255 }, prescale3[8] = { 0, 36, 72, 109, 145, 182, 218, 255 };
+
+#define STRBUFSIZ 512
+
+/*
+
+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 | 1 | base (bottom line from top)
+ 6 | 1 | inter (size of the interline)
+ 7 | X | char entries
+7+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
+Datas are stored in order X first, then Y.
+
+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 my word '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(Handle * ffont) : textcolor(255, 255, 255, 255), shadow(0), wspace(0) {
+ int i;
+
+ nbentries = ffont->readU16();
+ flags = ffont->readU8();
+ maxX = ffont->readU8();
+ maxY = ffont->readU8();
+ base = ffont->readU8();
+ inter = ffont->readU8();
+
+ nbcU = 256 / maxX;
+ nbcV = 256 / maxY;
+
+ nbcT = nbcU * nbcV;
+
+ nbT = nbentries / nbcT;
+
+ if (nbentries % nbcT) {
+ nbT++;
+ }
+
+ printm(M_INFO, "Creating font texture: %i entries, flags = 0x%02x, maxX = %i, maxY = %i\n", nbentries, flags, maxX, maxY);
+ printm(M_INFO, "Which makes %i texture(s), with %i char by texture, %i on X, and %i on Y\n", nbT, nbcT, nbcU, nbcV);
+
+ 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;
+ Uint32 curU = 0, curV = 0, curT = 0;
+ for (i = 0; i < nbentries; i++) {
+ sizes[i] = ffont->readU8();
+ for (int v = 0; v < maxY; v++) {
+ for (int u = 0; u < maxX; u++) {
+ Uint8 f;
+ f = ffont->readU8();
+ 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) + maxX) > 256) {
+ curU = 0;
+ if (((curV += maxY) + maxY) > 256) {
+ curV = 0;
+ if ((curT + 1) != nbT)
+ curtex = (Uint8 *) fonttex[++curT]->GetSurface()->pixels;
+ }
+ }
+ }
+
+ corresp = (Uint16 *) malloc(nbentries * 2 * sizeof(Uint16));
+
+ for (i = 0; i < 2 * nbentries; i++) {
+ corresp[i] = ffont->readU16();
+ }
+}
+
+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, int x, int y, ColorP c) {
+ bool was2D;
+ int trueentry, cx, cy, px, py;
+
+ return;
+
+ was2D = mogltk::glbase::is2D();
+
+ if (!was2D)
+ mogltk::glbase::Enter2DMode();
+
+ if (shadow) {
+ int os = shadow;
+ shadow = 0;
+
+ drawentry(entry, x + os, y + os, BLACK);
+
+ shadow = os;
+ }
+
+ y -= base;
+
+ Bind(entry / nbcT);
+ c.Bind();
+ trueentry = entry % nbcT;
+ cx = trueentry % nbcU;
+ cy = trueentry / nbcU;
+ px = cx * maxX;
+ py = cy * maxY;
+
+ glBegin(GL_TRIANGLE_STRIP);
+ glTexCoord2i(px , py ); glVertex2i(x , y );
+ glTexCoord2i(px + maxX - 1, py ); glVertex2i(x + maxX - 1, y );
+ glTexCoord2i(px , py + maxY - 1); glVertex2i(x , y + maxY - 1);
+ glTexCoord2i(px + maxX - 1, py + maxY - 1); glVertex2i(x + maxX - 1, y + maxY - 1);
+ glEnd();
+
+ if (!was2D)
+ mogltk::glbase::Leave2DMode();
+}
+
+void mogltk::font::putcursor(int x, int y) {
+ cx = ox = x;
+ cy = y;
+}
+
+void mogltk::font::putentry(Uint16 entry, ColorP c) {
+ drawentry(entry, cx, cy, c);
+ cx += sizes[entry] + wspace;
+}
+
+void mogltk::font::putchar(char ch, ColorP c) {
+ Uint16 * p;
+ int i;
+
+ for (i = 0, p = corresp; i < nbentries; i++, p++) {
+ if (*(p++) == ch) {
+ putentry(*p, c);
+ return;
+ }
+ }
+}
+
+int mogltk::font::getchar(char ch) const {
+ Uint16 * p;
+ int i;
+
+ for (i = 0, p = corresp; i < nbentries; i++, p++) {
+ if (*(p++) == ch) {
+ return *p;
+ }
+ }
+
+ return -1;
+}
+
+void mogltk::font::newline(void) {
+ cx = ox;
+ cy += inter;
+}
+
+int mogltk::font::printf(const ugly_string & m, va_list ap) {
+ char * p;
+ static char buffer[STRBUFSIZ + 1];
+ int r;
+
+#ifdef HAVE_VSNPRINTF
+ r = vsnprintf(buffer, STRBUFSIZ, m.p, ap);
+#else
+ r = vsprintf(buffer, m.p, ap);
+#endif
+
+ for (p = buffer; *p; p++) {
+ if (*p == '\n') {
+ newline();
+ } else {
+ putchar(*p, textcolor);
+ }
+ }
+
+ return r;
+}
+
+int mogltk::font::printf(const ugly_string & m, ...) {
+ va_list ap;
+ int r;
+
+ va_start(ap, m);
+ r = printf(m, ap);
+ va_end(ap);
+
+ return r;
+}
+
+int mogltk::font::printf(const char * p, ...) {
+ ugly_string m;
+ va_list ap;
+ int r;
+
+ m.p = p;
+
+ va_start(ap, p);
+ r = printf(m, ap);
+ va_end(ap);
+
+ return r;
+}
+
+void mogltk::font::setcolor(ColorP c) {
+ textcolor = c;
+}
+
+void mogltk::font::setshadow(int s) {
+ shadow = s;
+}
+
+void mogltk::font::setwspace(int w) {
+ wspace = w;
+}
+
+int mogltk::font::singletextsize(const String & s) const {
+ unsigned int i;
+ int r = 0;
+
+ for (i = 0; i < s.strlen(); i++) {
+ r += sizes[getchar(s[i])];
+ }
+
+ return r;
+}
+
+mogltk::font * mogltk::SystemFont;
+
+