--- /dev/null
+// The following implementation is based on TexFont API,
+// implementation and accompanying programs by Mark J. Kilgard.
+// Original license:
+
+/* Copyright (c) Mark J. Kilgard, 1997. */
+/* This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain. */
+
+#include "GLTextNS.h"
+
+#include <TMath.h>
+#include <TString.h>
+
+#include <GL/glu.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <Reve/Reve.h>
+#include <Reve/GLTextNS.h>
+
+using Reve::Exc_t;
+
+namespace GLTextNS {
+
+TexFont* fgDefaultFont = 0;
+
+#if 0
+/* Uncomment to debug various scenarios. */
+#undef GL_VERSION_1_1
+#undef GL_EXT_texture_object
+#undef GL_EXT_texture
+#endif
+
+int useLuminanceAlpha = 1;
+
+/* byte swap a 32-bit value */
+#define SWAPL(x, n) { \
+ n = ((char *) (x))[0]; \
+ ((char *) (x))[0] = ((char *) (x))[3]; \
+ ((char *) (x))[3] = n; \
+ n = ((char *) (x))[1]; \
+ ((char *) (x))[1] = ((char *) (x))[2]; \
+ ((char *) (x))[2] = n; }
+
+/* byte swap a short */
+#define SWAPS(x, n) { \
+ n = ((char *) (x))[0]; \
+ ((char *) (x))[0] = ((char *) (x))[1]; \
+ ((char *) (x))[1] = n; }
+
+/**************************************************************************/
+
+static TexGlyphVertexInfo* getTCVI(TexFont * txf, int c)
+{
+ TexGlyphVertexInfo *tgvi;
+
+ /* Automatically substitute uppercase letters with lowercase if not
+ uppercase available (and vice versa). */
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ tgvi = txf->lut[c - txf->min_glyph];
+ if (tgvi) {
+ return tgvi;
+ }
+ if (islower(c)) {
+ c = toupper(c);
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ return txf->lut[c - txf->min_glyph];
+ }
+ }
+ if (isupper(c)) {
+ c = tolower(c);
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ return txf->lut[c - txf->min_glyph];
+ }
+ }
+ }
+
+ //fprintf(stderr, "texfont: tried to access unavailable font character \"%c\" (%d)\n",
+ // isprint(c) ? c : ' ', c);
+
+ tgvi = txf->lut[' ' - txf->min_glyph];
+ if (tgvi) return tgvi;
+ tgvi = txf->lut['_' - txf->min_glyph];
+ if (tgvi) return tgvi;
+
+ return 0;
+}
+
+/**************************************************************************/
+
+static char *lastError;
+
+char* txfErrorString(void)
+{
+ return lastError;
+}
+
+/**************************************************************************/
+
+TexFont* txfLoadFont(const char *filename)
+{
+ TexFont *txf;
+ FILE *file;
+ GLfloat w, h, xstep, ystep;
+ char fileid[4], tmp;
+ unsigned char *texbitmap;
+ int min_glyph, max_glyph;
+ int endianness, swap, format, stride, width, height;
+ int i, j, got;
+
+ txf = NULL;
+ file = fopen(filename, "rb");
+ if (file == NULL) {
+ lastError = "file open failed.";
+ goto error;
+ }
+ txf = (TexFont *) malloc(sizeof(TexFont));
+ if (txf == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ /* For easy cleanup in error case. */
+ txf->texobj = 0; // MT add
+ txf->tgi = NULL;
+ txf->tgvi = NULL;
+ txf->lut = NULL;
+ txf->teximage = NULL;
+
+ got = fread(fileid, 1, 4, file);
+ if (got != 4 || strncmp(fileid, "\377txf", 4)) {
+ lastError = "not a texture font file.";
+ goto error;
+ }
+ assert(sizeof(int) == 4); /* Ensure external file format size. */
+ got = fread(&endianness, sizeof(int), 1, file);
+ if (got == 1 && endianness == 0x12345678) {
+ swap = 0;
+ } else if (got == 1 && endianness == 0x78563412) {
+ swap = 1;
+ } else {
+ lastError = "not a texture font file.";
+ goto error;
+ }
+#define EXPECT(n) if (got != n) { lastError = "premature end of file."; goto error; }
+ got = fread(&format, sizeof(int), 1, file);
+ EXPECT(1);
+ got = fread(&txf->tex_width, sizeof(int), 1, file);
+ EXPECT(1);
+ got = fread(&txf->tex_height, sizeof(int), 1, file);
+ EXPECT(1);
+ got = fread(&txf->max_ascent, sizeof(int), 1, file);
+ EXPECT(1);
+ got = fread(&txf->max_descent, sizeof(int), 1, file);
+ EXPECT(1);
+ got = fread(&txf->num_glyphs, sizeof(int), 1, file);
+ EXPECT(1);
+
+ if (swap) {
+ SWAPL(&format, tmp);
+ SWAPL(&txf->tex_width, tmp);
+ SWAPL(&txf->tex_height, tmp);
+ SWAPL(&txf->max_ascent, tmp);
+ SWAPL(&txf->max_descent, tmp);
+ SWAPL(&txf->num_glyphs, tmp);
+ }
+ txf->tgi = (TexGlyphInfo *) malloc(txf->num_glyphs * sizeof(TexGlyphInfo));
+ if (txf->tgi == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ assert(sizeof(TexGlyphInfo) == 12); /* Ensure external file format size. */
+ got = fread(txf->tgi, sizeof(TexGlyphInfo), txf->num_glyphs, file);
+ EXPECT(txf->num_glyphs);
+
+ if (swap) {
+ for (i = 0; i < txf->num_glyphs; i++) {
+ SWAPS(&txf->tgi[i].c, tmp);
+ SWAPS(&txf->tgi[i].x, tmp);
+ SWAPS(&txf->tgi[i].y, tmp);
+ }
+ }
+ txf->tgvi = (TexGlyphVertexInfo *)
+ malloc(txf->num_glyphs * sizeof(TexGlyphVertexInfo));
+ if (txf->tgvi == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ w = txf->tex_width;
+ h = txf->tex_height;
+ txf->max_width = 0;
+ xstep = 0.5 / w;
+ ystep = 0.5 / h;
+ for (i = 0; i < txf->num_glyphs; i++) {
+ TexGlyphInfo *tgi;
+
+ tgi = &txf->tgi[i];
+ txf->tgvi[i].t0[0] = tgi->x / w - xstep; // MT - xstep
+ txf->tgvi[i].t0[1] = tgi->y / h - ystep; // MT - ystep
+ txf->tgvi[i].v0[0] = tgi->xoffset;
+ txf->tgvi[i].v0[1] = tgi->yoffset;
+ txf->tgvi[i].t1[0] = (tgi->x + tgi->width) / w + xstep;
+ txf->tgvi[i].t1[1] = tgi->y / h - ystep; // MT - ystep
+ txf->tgvi[i].v1[0] = tgi->xoffset + tgi->width;
+ txf->tgvi[i].v1[1] = tgi->yoffset;
+ txf->tgvi[i].t2[0] = (tgi->x + tgi->width) / w + xstep;
+ txf->tgvi[i].t2[1] = (tgi->y + tgi->height) / h + ystep;
+ txf->tgvi[i].v2[0] = tgi->xoffset + tgi->width;
+ txf->tgvi[i].v2[1] = tgi->yoffset + tgi->height;
+ txf->tgvi[i].t3[0] = tgi->x / w - xstep; // MT - xstep
+ txf->tgvi[i].t3[1] = (tgi->y + tgi->height) / h + ystep;
+ txf->tgvi[i].v3[0] = tgi->xoffset;
+ txf->tgvi[i].v3[1] = tgi->yoffset + tgi->height;
+ txf->tgvi[i].advance = tgi->advance;
+
+ if(tgi->width > txf->max_width) txf->max_width = tgi->width;
+ }
+
+ min_glyph = txf->tgi[0].c;
+ max_glyph = txf->tgi[0].c;
+ for (i = 1; i < txf->num_glyphs; i++) {
+ if (txf->tgi[i].c < min_glyph) {
+ min_glyph = txf->tgi[i].c;
+ }
+ if (txf->tgi[i].c > max_glyph) {
+ max_glyph = txf->tgi[i].c;
+ }
+ }
+ txf->min_glyph = min_glyph;
+ txf->range = max_glyph - min_glyph + 1;
+
+ txf->lut = (TexGlyphVertexInfo **)
+ calloc(txf->range, sizeof(TexGlyphVertexInfo *));
+ if (txf->lut == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ for (i = 0; i < txf->num_glyphs; i++) {
+ txf->lut[txf->tgi[i].c - txf->min_glyph] = &txf->tgvi[i];
+ }
+
+ switch (format) {
+ case TXF_FORMAT_BYTE:
+ if (useLuminanceAlpha) {
+ unsigned char *orig;
+
+ orig = (unsigned char *) malloc(txf->tex_width * txf->tex_height);
+ if (orig == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ got = fread(orig, 1, txf->tex_width * txf->tex_height, file);
+ EXPECT(txf->tex_width * txf->tex_height);
+ txf->teximage = (unsigned char *)
+ malloc(2 * txf->tex_width * txf->tex_height);
+ if (txf->teximage == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ for (i = 0; i < txf->tex_width * txf->tex_height; i++) {
+ txf->teximage[i * 2] = orig[i];
+ txf->teximage[i * 2 + 1] = orig[i];
+ }
+ free(orig);
+ } else {
+ txf->teximage = (unsigned char *)
+ malloc(txf->tex_width * txf->tex_height);
+ if (txf->teximage == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ got = fread(txf->teximage, 1, txf->tex_width * txf->tex_height, file);
+ EXPECT(txf->tex_width * txf->tex_height);
+ }
+ break;
+ case TXF_FORMAT_BITMAP:
+ width = txf->tex_width;
+ height = txf->tex_height;
+ stride = (width + 7) >> 3;
+ texbitmap = (unsigned char *) malloc(stride * height);
+ if (texbitmap == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ got = fread(texbitmap, 1, stride * height, file);
+ EXPECT(stride * height);
+ if (useLuminanceAlpha) {
+ txf->teximage = (unsigned char *) calloc(width * height * 2, 1);
+ if (txf->teximage == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
+ txf->teximage[(i * width + j) * 2] = 255;
+ txf->teximage[(i * width + j) * 2 + 1] = 255;
+ }
+ }
+ }
+ } else {
+ txf->teximage = (unsigned char *) calloc(width * height, 1);
+ if (txf->teximage == NULL) {
+ lastError = "out of memory.";
+ goto error;
+ }
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
+ txf->teximage[i * width + j] = 255;
+ }
+ }
+ }
+ }
+ free(texbitmap);
+ break;
+ }
+
+ fclose(file);
+ return txf;
+
+error:
+
+ if (txf) {
+ if (txf->tgi)
+ free(txf->tgi);
+ if (txf->tgvi)
+ free(txf->tgvi);
+ if (txf->lut)
+ free(txf->lut);
+ if (txf->teximage)
+ free(txf->teximage);
+ free(txf);
+ }
+ if (file)
+ fclose(file);
+ return NULL;
+}
+
+/**************************************************************************/
+
+GLuint txfEstablishTexture(TexFont * txf, GLuint texobj,
+ GLboolean setupMipmaps)
+{
+ if (txf->texobj == 0) {
+ if (texobj == 0) {
+ glGenTextures(1, &txf->texobj);
+ } else {
+ txf->texobj = texobj;
+ }
+ }
+ glBindTexture(GL_TEXTURE_2D, txf->texobj);
+
+ if (useLuminanceAlpha) {
+ if (setupMipmaps) {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA,
+ txf->tex_width, txf->tex_height,
+ GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, txf->teximage);
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
+ txf->tex_width, txf->tex_height, 0,
+ GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, txf->teximage);
+ }
+ } else {
+ if (setupMipmaps) {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, GL_INTENSITY4,
+ txf->tex_width, txf->tex_height,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, txf->teximage);
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4,
+ txf->tex_width, txf->tex_height, 0,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, txf->teximage);
+ }
+ }
+
+ // MT: tried changing MIN/MAG filters ... bad idea.
+
+ return txf->texobj;
+}
+
+/**************************************************************************/
+
+void txfBindFontTexture(TexFont * txf)
+{
+ glBindTexture(GL_TEXTURE_2D, txf->texobj);
+}
+
+/**************************************************************************/
+
+void txfUnloadFont(TexFont * txf)
+{
+ if (txf->texobj) {
+ glDeleteTextures(1, &txf->texobj);
+ }
+ if (txf->teximage) {
+ free(txf->teximage);
+ }
+ free(txf->tgi);
+ free(txf->tgvi);
+ free(txf->lut);
+ free(txf);
+}
+
+/**************************************************************************/
+
+void txfGetStringMetrics(TexFont * txf, const char *TString, int len,
+ int &width, int &max_ascent, int &max_descent)
+{
+ TexGlyphVertexInfo *tgvi;
+ int w, i;
+ int ma = 0, md = 0;
+
+ w = 0;
+ for (i = 0; i < len; i++) {
+ if (TString[i] == 27) {
+ switch (TString[i + 1]) {
+ case 'M':
+ i += 4;
+ break;
+ case 'T':
+ i += 7;
+ break;
+ case 'L':
+ i += 7;
+ break;
+ case 'F':
+ i += 13;
+ break;
+ }
+ } else {
+ tgvi = getTCVI(txf, TString[i]);
+ w += int(tgvi->advance);
+ ma = TMath::Max(ma, (int)( tgvi->v3[1]));
+ md = TMath::Max(md, (int)(-tgvi->v0[1]));
+ }
+ }
+ width = w;
+ max_ascent = ma; // txf->max_ascent;
+ max_descent = md; // txf->max_descent;
+ // printf("%d %d %d %d\n", txf->max_ascent, txf->max_descent, ma, md);
+}
+
+/**************************************************************************/
+
+void txfRenderGlyph(TexFont * txf, int c)
+{
+ TexGlyphVertexInfo *tgvi;
+
+ tgvi = getTCVI(txf, c);
+ glBegin(GL_QUADS);
+ glTexCoord2fv(tgvi->t0);
+ glVertex2sv(tgvi->v0);
+ glTexCoord2fv(tgvi->t1);
+ glVertex2sv(tgvi->v1);
+ glTexCoord2fv(tgvi->t2);
+ glVertex2sv(tgvi->v2);
+ glTexCoord2fv(tgvi->t3);
+ glVertex2sv(tgvi->v3);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+}
+
+void txfRenderString(TexFont * txf, const char *TString, int len,
+ bool keep_pos)
+{
+ int i;
+ if(keep_pos) glPushMatrix();
+ for (i = 0; i < len; i++) {
+ txfRenderGlyph(txf, TString[i]);
+ }
+ if(keep_pos) glPopMatrix();
+}
+
+void txfRenderString(TexFont * txf, const char *TString, int len,
+ GLfloat maxx, GLfloat fadew,
+ bool keep_pos)
+{
+ GLfloat x = 0, xg0, xg1, yg0, yg1, f0, f1;
+ fadew *= txf->max_width;
+ GLfloat xfade = maxx - fadew;
+
+ GLfloat col[4];
+ glGetFloatv(GL_CURRENT_COLOR, col);
+
+ glBegin(GL_QUADS);
+ for (int i = 0; i < len; i++) {
+
+ TexGlyphVertexInfo *tgvi;
+
+ tgvi = getTCVI(txf, TString[i]);
+
+ xg0 = x + tgvi->v0[0];
+ xg1 = x + tgvi->v1[0];
+ yg0 = tgvi->v0[1];
+ yg1 = tgvi->v2[1];
+
+ if(xg1 > xfade) {
+ f0 = 1; if(xg0 > xfade) f0 *= 1 - (xg0-xfade)/fadew;
+ f1 = 1 - (xg1-xfade)/fadew;
+
+ // printf("XX %s %c %f %f x(%f,%f) y(%f,%f)\n",
+ // TString, TString[i], f0, f1,
+ // xg0, xg1,yg0, yg1);
+
+ glColor4f(f0*col[0], f0*col[1], f0*col[2], f0*col[3]);
+ glTexCoord2fv(tgvi->t0); glVertex2f(xg0, yg0);
+ glColor4f(f1*col[0], f1*col[1], f1*col[2], f1*col[3]);
+ glTexCoord2fv(tgvi->t1); glVertex2f(xg1, yg0);
+ glTexCoord2fv(tgvi->t2); glVertex2f(xg1, yg1);
+ glColor4f(f0*col[0], f0*col[1], f0*col[2], f0*col[3]);
+ glTexCoord2fv(tgvi->t3); glVertex2f(xg0, yg1);
+ } else {
+ glTexCoord2fv(tgvi->t0); glVertex2f(xg0, yg0);
+ glTexCoord2fv(tgvi->t1); glVertex2f(xg1, yg0);
+ glTexCoord2fv(tgvi->t2); glVertex2f(xg1, yg1);
+ glTexCoord2fv(tgvi->t3); glVertex2f(xg0, yg1);
+ }
+
+ x += tgvi->advance;
+ if(x > maxx) break;
+ }
+ glEnd();
+
+ if(!keep_pos) glTranslatef(x, 0.0, 0.0);
+}
+
+/**************************************************************************/
+
+void txfRenderGlyphZW(TexFont * txf, int c, float z, float w)
+{
+ TexGlyphVertexInfo *tgvi;
+
+ tgvi = getTCVI(txf, c);
+ glBegin(GL_QUADS);
+ glTexCoord2fv(tgvi->t0);
+ glVertex4f(tgvi->v0[0], tgvi->v0[1], z, w);
+ glTexCoord2fv(tgvi->t1);
+ glVertex4f(tgvi->v1[0], tgvi->v1[1], z, w);
+ glTexCoord2fv(tgvi->t2);
+ glVertex4f(tgvi->v2[0], tgvi->v2[1], z, w);
+ glTexCoord2fv(tgvi->t3);
+ glVertex4f(tgvi->v3[0], tgvi->v3[1], z, w);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+}
+
+void txfRenderStringZW(TexFont * txf, const char *TString, int len,
+ float z, float w, bool keep_pos)
+{
+ int i;
+
+ if(keep_pos) glPushMatrix();
+ for (i = 0; i < len; i++) {
+ txfRenderGlyphZW(txf, TString[i], z, w);
+ }
+ if(keep_pos) glPopMatrix();
+}
+
+/**************************************************************************/
+
+enum {
+ MONO, TOP_BOTTOM, LEFT_RIGHT, FOUR
+};
+
+/**************************************************************************/
+
+void txfRenderFancyString(TexFont * txf, char *TString, int len)
+{
+ TexGlyphVertexInfo *tgvi;
+ GLubyte c[4][3];
+ int mode = MONO;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (TString[i] == 27) {
+ switch (TString[i + 1]) {
+ case 'M':
+ mode = MONO;
+ glColor3ubv((GLubyte *) & TString[i + 2]);
+ i += 4;
+ break;
+ case 'T':
+ mode = TOP_BOTTOM;
+ memcpy(c, &TString[i + 2], 6);
+ i += 7;
+ break;
+ case 'L':
+ mode = LEFT_RIGHT;
+ memcpy(c, &TString[i + 2], 6);
+ i += 7;
+ break;
+ case 'F':
+ mode = FOUR;
+ memcpy(c, &TString[i + 2], 12);
+ i += 13;
+ break;
+ }
+ } else {
+ switch (mode) {
+ case MONO:
+ txfRenderGlyph(txf, TString[i]);
+ break;
+ case TOP_BOTTOM:
+ tgvi = getTCVI(txf, TString[i]);
+ glBegin(GL_QUADS);
+ glColor3ubv(c[0]);
+ glTexCoord2fv(tgvi->t0);
+ glVertex2sv(tgvi->v0);
+ glTexCoord2fv(tgvi->t1);
+ glVertex2sv(tgvi->v1);
+ glColor3ubv(c[1]);
+ glTexCoord2fv(tgvi->t2);
+ glVertex2sv(tgvi->v2);
+ glTexCoord2fv(tgvi->t3);
+ glVertex2sv(tgvi->v3);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+ break;
+ case LEFT_RIGHT:
+ tgvi = getTCVI(txf, TString[i]);
+ glBegin(GL_QUADS);
+ glColor3ubv(c[0]);
+ glTexCoord2fv(tgvi->t0);
+ glVertex2sv(tgvi->v0);
+ glColor3ubv(c[1]);
+ glTexCoord2fv(tgvi->t1);
+ glVertex2sv(tgvi->v1);
+ glColor3ubv(c[1]);
+ glTexCoord2fv(tgvi->t2);
+ glVertex2sv(tgvi->v2);
+ glColor3ubv(c[0]);
+ glTexCoord2fv(tgvi->t3);
+ glVertex2sv(tgvi->v3);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+ break;
+ case FOUR:
+ tgvi = getTCVI(txf, TString[i]);
+ glBegin(GL_QUADS);
+ glColor3ubv(c[0]);
+ glTexCoord2fv(tgvi->t0);
+ glVertex2sv(tgvi->v0);
+ glColor3ubv(c[1]);
+ glTexCoord2fv(tgvi->t1);
+ glVertex2sv(tgvi->v1);
+ glColor3ubv(c[2]);
+ glTexCoord2fv(tgvi->t2);
+ glVertex2sv(tgvi->v2);
+ glColor3ubv(c[3]);
+ glTexCoord2fv(tgvi->t3);
+ glVertex2sv(tgvi->v3);
+ glEnd();
+ glTranslatef(tgvi->advance, 0.0, 0.0);
+ break;
+ }
+ }
+ }
+}
+
+/**************************************************************************/
+
+int txfInFont(TexFont * txf, int c)
+{
+ /* NOTE: No uppercase/lowercase substituion. */
+ if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
+ if (txf->lut[c - txf->min_glyph]) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**************************************************************************/
+
+bool LoadDefaultFont( TString file)
+{
+ static const Exc_t _eh("GLTextNS::LoadFont ");
+
+ if(fgDefaultFont) {
+ txfUnloadFont(fgDefaultFont);
+ fgDefaultFont = 0;
+ }
+
+ fgDefaultFont = GLTextNS::txfLoadFont(file.Data());
+ if(fgDefaultFont != 0) {
+ txfEstablishTexture(fgDefaultFont, 0, GL_TRUE);
+ return true;
+ }
+ else {
+ throw(_eh + Form("Error loading font from file '%s': %s",
+ file.Data(), txfErrorString()));
+ }
+
+ return false;
+}
+
+} // end GLTextNS
--- /dev/null
+
+#ifndef Reve_GLTextNS_H
+#define Reve_GLTextNS_H
+
+// The following implementation is based on TexFont API,
+// implementation and accompanying programs by Mark J. Kilgard.
+// Original license:
+
+/* Copyright (c) Mark J. Kilgard, 1997. */
+/* This program is freely distributable without licensing fees and is
+ provided without guarantee or warrantee expressed or implied. This
+ program is -not- in the public domain. */
+
+#ifndef __CINT__
+
+#include <TObject.h>
+#include <TGLIncludes.h>
+
+class TString;
+
+namespace GLTextNS {
+
+#define TXF_FORMAT_BYTE 0
+#define TXF_FORMAT_BITMAP 1
+
+struct TexGlyphInfo {
+ unsigned short c; /* Potentially support 16-bit glyphs. */
+ unsigned char width;
+ unsigned char height;
+ signed char xoffset;
+ signed char yoffset;
+ signed char advance;
+ char dummy; /* Space holder for alignment reasons. */
+ short x;
+ short y;
+};
+
+struct TexGlyphVertexInfo {
+ GLfloat t0[2];
+ GLshort v0[2];
+ GLfloat t1[2];
+ GLshort v1[2];
+ GLfloat t2[2];
+ GLshort v2[2];
+ GLfloat t3[2];
+ GLshort v3[2];
+ GLfloat advance;
+};
+
+class TexFont : public TObject {
+public:
+ GLuint texobj;
+ int tex_width;
+ int tex_height;
+ int max_ascent;
+ int max_descent;
+ int max_width; // max glyph width (MT)
+ int num_glyphs;
+ int min_glyph;
+ int range;
+ unsigned char *teximage;
+ TexGlyphInfo *tgi;
+ TexGlyphVertexInfo *tgvi;
+ TexGlyphVertexInfo **lut;
+
+ int max_height() { return max_ascent + max_descent; }
+};
+
+
+extern char *txfErrorString(void);
+
+extern TexFont *txfLoadFont(const char *filename);
+
+extern void txfUnloadFont(TexFont* txf);
+
+extern GLuint txfEstablishTexture(TexFont* txf, GLuint texobj,
+ GLboolean setupMipmaps);
+
+extern void txfBindFontTexture(TexFont* txf);
+
+extern void txfGetStringMetrics(TexFont* txf, const char *TString, int len,
+ int &width, int &max_ascent, int &max_descent);
+
+extern void txfRenderGlyph(TexFont* txf, int c);
+extern void txfRenderString(TexFont* txf, const char *TString, int len,
+ bool keep_pos=true);
+extern void txfRenderString(TexFont* txf, const char *TString, int len,
+ GLfloat maxx, GLfloat fadew,
+ bool keep_pos=true);
+
+extern void txfRenderGlyphZW(TexFont* txf, int c, float z, float w);
+extern void txfRenderStringZW(TexFont* txf, const char *TString, int len,
+ float z, float w, bool keep_pos=true);
+
+extern void txfRenderFancyString(TexFont* txf, char *TString, int len);
+
+
+bool LoadDefaultFont(TString font_file);
+
+extern TexFont* fgDefaultFont;
+
+/**************************************************************************/
+// Here starts MT higher-level interface
+/**************************************************************************/
+/*
+ struct BoxSpecs {
+ int lm, rm, tm, bm;
+ int lineskip;
+ char align;
+ TString pos;
+
+ void _init() { align = 'l'; lineskip = 0; }
+
+ BoxSpecs()
+ { lm = rm = 3; tm = 0; bm = 2; _init(); }
+
+ BoxSpecs(int lr, int tb)
+ { lm = rm = lr; tm = bm = tb; _init(); }
+
+ BoxSpecs(int l, int r, int t, int b)
+ { lm = l; rm = r; tm = t; bm = b; _init(); }
+ };
+ struct TextLineData {
+ int width, ascent, descent, hfull;
+ TString text;
+
+ TextLineData(TexFont *txf, TString line);
+ };
+
+ extern void RnrTextBar(RnrDriver* rd, const TString& text);
+
+ extern void RnrTextBar(RnrDriver* rd, const TString& text,
+ BoxSpecs& bs, float zoffset=0);
+
+ extern void RnrTextPoly(RnrDriver* rd, const TString& text);
+
+ extern void RnrText(RnrDriver* rd, const TString& text,
+ int x, int y, float z,
+ const ZColor* front_col, const ZColor* back_col=0);
+
+ extern void RnrTextAt(RnrDriver* rd, const TString& text,
+ int x, int yrow, float z,
+ const ZColor* front_col, const ZColor* back_col=0);
+*/
+
+} // namescape GLTextNS
+
+#endif // cint
+#endif // Reve_GLTextNS_H