]> git.uio.no Git - u/mrichter/AliRoot.git/blame - EVE/Reve/GLTextNS.cxx
Runloader is updated when moving to next file (quick fix).
[u/mrichter/AliRoot.git] / EVE / Reve / GLTextNS.cxx
CommitLineData
b6b64776 1// The following implementation is based on TexFont API,
2// implementation and accompanying programs by Mark J. Kilgard.
3// Original license:
4
5/* Copyright (c) Mark J. Kilgard, 1997. */
6/* This program is freely distributable without licensing fees and is
7 provided without guarantee or warrantee expressed or implied. This
8 program is -not- in the public domain. */
9
10#include "GLTextNS.h"
11
12#include <TMath.h>
13#include <TString.h>
14
15#include <GL/glu.h>
16
17#include <assert.h>
18#include <ctype.h>
19#include <stdlib.h>
20#include <stdio.h>
21
22#include <Reve/Reve.h>
23#include <Reve/GLTextNS.h>
24
25using Reve::Exc_t;
26
27namespace GLTextNS {
28
29TexFont* fgDefaultFont = 0;
30
31#if 0
32/* Uncomment to debug various scenarios. */
33#undef GL_VERSION_1_1
34#undef GL_EXT_texture_object
35#undef GL_EXT_texture
36#endif
37
38int useLuminanceAlpha = 1;
39
40/* byte swap a 32-bit value */
41#define SWAPL(x, n) { \
42 n = ((char *) (x))[0]; \
43 ((char *) (x))[0] = ((char *) (x))[3]; \
44 ((char *) (x))[3] = n; \
45 n = ((char *) (x))[1]; \
46 ((char *) (x))[1] = ((char *) (x))[2]; \
47 ((char *) (x))[2] = n; }
48
49/* byte swap a short */
50#define SWAPS(x, n) { \
51 n = ((char *) (x))[0]; \
52 ((char *) (x))[0] = ((char *) (x))[1]; \
53 ((char *) (x))[1] = n; }
54
55/**************************************************************************/
56
57static TexGlyphVertexInfo* getTCVI(TexFont * txf, int c)
58{
59 TexGlyphVertexInfo *tgvi;
60
61 /* Automatically substitute uppercase letters with lowercase if not
62 uppercase available (and vice versa). */
63 if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
64 tgvi = txf->lut[c - txf->min_glyph];
65 if (tgvi) {
66 return tgvi;
67 }
68 if (islower(c)) {
69 c = toupper(c);
70 if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
71 return txf->lut[c - txf->min_glyph];
72 }
73 }
74 if (isupper(c)) {
75 c = tolower(c);
76 if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
77 return txf->lut[c - txf->min_glyph];
78 }
79 }
80 }
81
82 //fprintf(stderr, "texfont: tried to access unavailable font character \"%c\" (%d)\n",
83 // isprint(c) ? c : ' ', c);
84
85 tgvi = txf->lut[' ' - txf->min_glyph];
86 if (tgvi) return tgvi;
87 tgvi = txf->lut['_' - txf->min_glyph];
88 if (tgvi) return tgvi;
89
90 return 0;
91}
92
93/**************************************************************************/
94
95static char *lastError;
96
97char* txfErrorString(void)
98{
99 return lastError;
100}
101
102/**************************************************************************/
103
104TexFont* txfLoadFont(const char *filename)
105{
106 TexFont *txf;
107 FILE *file;
108 GLfloat w, h, xstep, ystep;
109 char fileid[4], tmp;
110 unsigned char *texbitmap;
111 int min_glyph, max_glyph;
112 int endianness, swap, format, stride, width, height;
113 int i, j, got;
114
115 txf = NULL;
116 file = fopen(filename, "rb");
117 if (file == NULL) {
118 lastError = "file open failed.";
119 goto error;
120 }
121 txf = (TexFont *) malloc(sizeof(TexFont));
122 if (txf == NULL) {
123 lastError = "out of memory.";
124 goto error;
125 }
126 /* For easy cleanup in error case. */
127 txf->texobj = 0; // MT add
128 txf->tgi = NULL;
129 txf->tgvi = NULL;
130 txf->lut = NULL;
131 txf->teximage = NULL;
132
133 got = fread(fileid, 1, 4, file);
134 if (got != 4 || strncmp(fileid, "\377txf", 4)) {
135 lastError = "not a texture font file.";
136 goto error;
137 }
138 assert(sizeof(int) == 4); /* Ensure external file format size. */
139 got = fread(&endianness, sizeof(int), 1, file);
140 if (got == 1 && endianness == 0x12345678) {
141 swap = 0;
142 } else if (got == 1 && endianness == 0x78563412) {
143 swap = 1;
144 } else {
145 lastError = "not a texture font file.";
146 goto error;
147 }
148#define EXPECT(n) if (got != n) { lastError = "premature end of file."; goto error; }
149 got = fread(&format, sizeof(int), 1, file);
150 EXPECT(1);
151 got = fread(&txf->tex_width, sizeof(int), 1, file);
152 EXPECT(1);
153 got = fread(&txf->tex_height, sizeof(int), 1, file);
154 EXPECT(1);
155 got = fread(&txf->max_ascent, sizeof(int), 1, file);
156 EXPECT(1);
157 got = fread(&txf->max_descent, sizeof(int), 1, file);
158 EXPECT(1);
159 got = fread(&txf->num_glyphs, sizeof(int), 1, file);
160 EXPECT(1);
161
162 if (swap) {
163 SWAPL(&format, tmp);
164 SWAPL(&txf->tex_width, tmp);
165 SWAPL(&txf->tex_height, tmp);
166 SWAPL(&txf->max_ascent, tmp);
167 SWAPL(&txf->max_descent, tmp);
168 SWAPL(&txf->num_glyphs, tmp);
169 }
170 txf->tgi = (TexGlyphInfo *) malloc(txf->num_glyphs * sizeof(TexGlyphInfo));
171 if (txf->tgi == NULL) {
172 lastError = "out of memory.";
173 goto error;
174 }
175 assert(sizeof(TexGlyphInfo) == 12); /* Ensure external file format size. */
176 got = fread(txf->tgi, sizeof(TexGlyphInfo), txf->num_glyphs, file);
177 EXPECT(txf->num_glyphs);
178
179 if (swap) {
180 for (i = 0; i < txf->num_glyphs; i++) {
181 SWAPS(&txf->tgi[i].c, tmp);
182 SWAPS(&txf->tgi[i].x, tmp);
183 SWAPS(&txf->tgi[i].y, tmp);
184 }
185 }
186 txf->tgvi = (TexGlyphVertexInfo *)
187 malloc(txf->num_glyphs * sizeof(TexGlyphVertexInfo));
188 if (txf->tgvi == NULL) {
189 lastError = "out of memory.";
190 goto error;
191 }
192 w = txf->tex_width;
193 h = txf->tex_height;
194 txf->max_width = 0;
195 xstep = 0.5 / w;
196 ystep = 0.5 / h;
197 for (i = 0; i < txf->num_glyphs; i++) {
198 TexGlyphInfo *tgi;
199
200 tgi = &txf->tgi[i];
201 txf->tgvi[i].t0[0] = tgi->x / w - xstep; // MT - xstep
202 txf->tgvi[i].t0[1] = tgi->y / h - ystep; // MT - ystep
203 txf->tgvi[i].v0[0] = tgi->xoffset;
204 txf->tgvi[i].v0[1] = tgi->yoffset;
205 txf->tgvi[i].t1[0] = (tgi->x + tgi->width) / w + xstep;
206 txf->tgvi[i].t1[1] = tgi->y / h - ystep; // MT - ystep
207 txf->tgvi[i].v1[0] = tgi->xoffset + tgi->width;
208 txf->tgvi[i].v1[1] = tgi->yoffset;
209 txf->tgvi[i].t2[0] = (tgi->x + tgi->width) / w + xstep;
210 txf->tgvi[i].t2[1] = (tgi->y + tgi->height) / h + ystep;
211 txf->tgvi[i].v2[0] = tgi->xoffset + tgi->width;
212 txf->tgvi[i].v2[1] = tgi->yoffset + tgi->height;
213 txf->tgvi[i].t3[0] = tgi->x / w - xstep; // MT - xstep
214 txf->tgvi[i].t3[1] = (tgi->y + tgi->height) / h + ystep;
215 txf->tgvi[i].v3[0] = tgi->xoffset;
216 txf->tgvi[i].v3[1] = tgi->yoffset + tgi->height;
217 txf->tgvi[i].advance = tgi->advance;
218
219 if(tgi->width > txf->max_width) txf->max_width = tgi->width;
220 }
221
222 min_glyph = txf->tgi[0].c;
223 max_glyph = txf->tgi[0].c;
224 for (i = 1; i < txf->num_glyphs; i++) {
225 if (txf->tgi[i].c < min_glyph) {
226 min_glyph = txf->tgi[i].c;
227 }
228 if (txf->tgi[i].c > max_glyph) {
229 max_glyph = txf->tgi[i].c;
230 }
231 }
232 txf->min_glyph = min_glyph;
233 txf->range = max_glyph - min_glyph + 1;
234
235 txf->lut = (TexGlyphVertexInfo **)
236 calloc(txf->range, sizeof(TexGlyphVertexInfo *));
237 if (txf->lut == NULL) {
238 lastError = "out of memory.";
239 goto error;
240 }
241 for (i = 0; i < txf->num_glyphs; i++) {
242 txf->lut[txf->tgi[i].c - txf->min_glyph] = &txf->tgvi[i];
243 }
244
245 switch (format) {
246 case TXF_FORMAT_BYTE:
247 if (useLuminanceAlpha) {
248 unsigned char *orig;
249
250 orig = (unsigned char *) malloc(txf->tex_width * txf->tex_height);
251 if (orig == NULL) {
252 lastError = "out of memory.";
253 goto error;
254 }
255 got = fread(orig, 1, txf->tex_width * txf->tex_height, file);
256 EXPECT(txf->tex_width * txf->tex_height);
257 txf->teximage = (unsigned char *)
258 malloc(2 * txf->tex_width * txf->tex_height);
259 if (txf->teximage == NULL) {
260 lastError = "out of memory.";
261 goto error;
262 }
263 for (i = 0; i < txf->tex_width * txf->tex_height; i++) {
264 txf->teximage[i * 2] = orig[i];
265 txf->teximage[i * 2 + 1] = orig[i];
266 }
267 free(orig);
268 } else {
269 txf->teximage = (unsigned char *)
270 malloc(txf->tex_width * txf->tex_height);
271 if (txf->teximage == NULL) {
272 lastError = "out of memory.";
273 goto error;
274 }
275 got = fread(txf->teximage, 1, txf->tex_width * txf->tex_height, file);
276 EXPECT(txf->tex_width * txf->tex_height);
277 }
278 break;
279 case TXF_FORMAT_BITMAP:
280 width = txf->tex_width;
281 height = txf->tex_height;
282 stride = (width + 7) >> 3;
283 texbitmap = (unsigned char *) malloc(stride * height);
284 if (texbitmap == NULL) {
285 lastError = "out of memory.";
286 goto error;
287 }
288 got = fread(texbitmap, 1, stride * height, file);
289 EXPECT(stride * height);
290 if (useLuminanceAlpha) {
291 txf->teximage = (unsigned char *) calloc(width * height * 2, 1);
292 if (txf->teximage == NULL) {
293 lastError = "out of memory.";
294 goto error;
295 }
296 for (i = 0; i < height; i++) {
297 for (j = 0; j < width; j++) {
298 if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
299 txf->teximage[(i * width + j) * 2] = 255;
300 txf->teximage[(i * width + j) * 2 + 1] = 255;
301 }
302 }
303 }
304 } else {
305 txf->teximage = (unsigned char *) calloc(width * height, 1);
306 if (txf->teximage == NULL) {
307 lastError = "out of memory.";
308 goto error;
309 }
310 for (i = 0; i < height; i++) {
311 for (j = 0; j < width; j++) {
312 if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
313 txf->teximage[i * width + j] = 255;
314 }
315 }
316 }
317 }
318 free(texbitmap);
319 break;
320 }
321
322 fclose(file);
323 return txf;
324
325error:
326
327 if (txf) {
328 if (txf->tgi)
329 free(txf->tgi);
330 if (txf->tgvi)
331 free(txf->tgvi);
332 if (txf->lut)
333 free(txf->lut);
334 if (txf->teximage)
335 free(txf->teximage);
336 free(txf);
337 }
338 if (file)
339 fclose(file);
340 return NULL;
341}
342
343/**************************************************************************/
344
345GLuint txfEstablishTexture(TexFont * txf, GLuint texobj,
346 GLboolean setupMipmaps)
347{
348 if (txf->texobj == 0) {
349 if (texobj == 0) {
350 glGenTextures(1, &txf->texobj);
351 } else {
352 txf->texobj = texobj;
353 }
354 }
355 glBindTexture(GL_TEXTURE_2D, txf->texobj);
356
357 if (useLuminanceAlpha) {
358 if (setupMipmaps) {
359 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA,
360 txf->tex_width, txf->tex_height,
361 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, txf->teximage);
362 } else {
363 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
364 txf->tex_width, txf->tex_height, 0,
365 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, txf->teximage);
366 }
367 } else {
368 if (setupMipmaps) {
369 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_INTENSITY4,
370 txf->tex_width, txf->tex_height,
371 GL_LUMINANCE, GL_UNSIGNED_BYTE, txf->teximage);
372 } else {
373 glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4,
374 txf->tex_width, txf->tex_height, 0,
375 GL_LUMINANCE, GL_UNSIGNED_BYTE, txf->teximage);
376 }
377 }
378
379 // MT: tried changing MIN/MAG filters ... bad idea.
380
381 return txf->texobj;
382}
383
384/**************************************************************************/
385
386void txfBindFontTexture(TexFont * txf)
387{
388 glBindTexture(GL_TEXTURE_2D, txf->texobj);
389}
390
391/**************************************************************************/
392
393void txfUnloadFont(TexFont * txf)
394{
395 if (txf->texobj) {
396 glDeleteTextures(1, &txf->texobj);
397 }
398 if (txf->teximage) {
399 free(txf->teximage);
400 }
401 free(txf->tgi);
402 free(txf->tgvi);
403 free(txf->lut);
404 free(txf);
405}
406
407/**************************************************************************/
408
409void txfGetStringMetrics(TexFont * txf, const char *TString, int len,
410 int &width, int &max_ascent, int &max_descent)
411{
412 TexGlyphVertexInfo *tgvi;
413 int w, i;
414 int ma = 0, md = 0;
415
416 w = 0;
417 for (i = 0; i < len; i++) {
418 if (TString[i] == 27) {
419 switch (TString[i + 1]) {
420 case 'M':
421 i += 4;
422 break;
423 case 'T':
424 i += 7;
425 break;
426 case 'L':
427 i += 7;
428 break;
429 case 'F':
430 i += 13;
431 break;
432 }
433 } else {
434 tgvi = getTCVI(txf, TString[i]);
435 w += int(tgvi->advance);
436 ma = TMath::Max(ma, (int)( tgvi->v3[1]));
437 md = TMath::Max(md, (int)(-tgvi->v0[1]));
438 }
439 }
440 width = w;
441 max_ascent = ma; // txf->max_ascent;
442 max_descent = md; // txf->max_descent;
443 // printf("%d %d %d %d\n", txf->max_ascent, txf->max_descent, ma, md);
444}
445
446/**************************************************************************/
447
448void txfRenderGlyph(TexFont * txf, int c)
449{
450 TexGlyphVertexInfo *tgvi;
451
452 tgvi = getTCVI(txf, c);
453 glBegin(GL_QUADS);
454 glTexCoord2fv(tgvi->t0);
455 glVertex2sv(tgvi->v0);
456 glTexCoord2fv(tgvi->t1);
457 glVertex2sv(tgvi->v1);
458 glTexCoord2fv(tgvi->t2);
459 glVertex2sv(tgvi->v2);
460 glTexCoord2fv(tgvi->t3);
461 glVertex2sv(tgvi->v3);
462 glEnd();
463 glTranslatef(tgvi->advance, 0.0, 0.0);
464}
465
466void txfRenderString(TexFont * txf, const char *TString, int len,
467 bool keep_pos)
468{
469 int i;
470 if(keep_pos) glPushMatrix();
471 for (i = 0; i < len; i++) {
472 txfRenderGlyph(txf, TString[i]);
473 }
474 if(keep_pos) glPopMatrix();
475}
476
477void txfRenderString(TexFont * txf, const char *TString, int len,
478 GLfloat maxx, GLfloat fadew,
479 bool keep_pos)
480{
481 GLfloat x = 0, xg0, xg1, yg0, yg1, f0, f1;
482 fadew *= txf->max_width;
483 GLfloat xfade = maxx - fadew;
484
485 GLfloat col[4];
486 glGetFloatv(GL_CURRENT_COLOR, col);
487
488 glBegin(GL_QUADS);
489 for (int i = 0; i < len; i++) {
490
491 TexGlyphVertexInfo *tgvi;
492
493 tgvi = getTCVI(txf, TString[i]);
494
495 xg0 = x + tgvi->v0[0];
496 xg1 = x + tgvi->v1[0];
497 yg0 = tgvi->v0[1];
498 yg1 = tgvi->v2[1];
499
500 if(xg1 > xfade) {
501 f0 = 1; if(xg0 > xfade) f0 *= 1 - (xg0-xfade)/fadew;
502 f1 = 1 - (xg1-xfade)/fadew;
503
504 // printf("XX %s %c %f %f x(%f,%f) y(%f,%f)\n",
505 // TString, TString[i], f0, f1,
506 // xg0, xg1,yg0, yg1);
507
508 glColor4f(f0*col[0], f0*col[1], f0*col[2], f0*col[3]);
509 glTexCoord2fv(tgvi->t0); glVertex2f(xg0, yg0);
510 glColor4f(f1*col[0], f1*col[1], f1*col[2], f1*col[3]);
511 glTexCoord2fv(tgvi->t1); glVertex2f(xg1, yg0);
512 glTexCoord2fv(tgvi->t2); glVertex2f(xg1, yg1);
513 glColor4f(f0*col[0], f0*col[1], f0*col[2], f0*col[3]);
514 glTexCoord2fv(tgvi->t3); glVertex2f(xg0, yg1);
515 } else {
516 glTexCoord2fv(tgvi->t0); glVertex2f(xg0, yg0);
517 glTexCoord2fv(tgvi->t1); glVertex2f(xg1, yg0);
518 glTexCoord2fv(tgvi->t2); glVertex2f(xg1, yg1);
519 glTexCoord2fv(tgvi->t3); glVertex2f(xg0, yg1);
520 }
521
522 x += tgvi->advance;
523 if(x > maxx) break;
524 }
525 glEnd();
526
527 if(!keep_pos) glTranslatef(x, 0.0, 0.0);
528}
529
530/**************************************************************************/
531
532void txfRenderGlyphZW(TexFont * txf, int c, float z, float w)
533{
534 TexGlyphVertexInfo *tgvi;
535
536 tgvi = getTCVI(txf, c);
537 glBegin(GL_QUADS);
538 glTexCoord2fv(tgvi->t0);
539 glVertex4f(tgvi->v0[0], tgvi->v0[1], z, w);
540 glTexCoord2fv(tgvi->t1);
541 glVertex4f(tgvi->v1[0], tgvi->v1[1], z, w);
542 glTexCoord2fv(tgvi->t2);
543 glVertex4f(tgvi->v2[0], tgvi->v2[1], z, w);
544 glTexCoord2fv(tgvi->t3);
545 glVertex4f(tgvi->v3[0], tgvi->v3[1], z, w);
546 glEnd();
547 glTranslatef(tgvi->advance, 0.0, 0.0);
548}
549
550void txfRenderStringZW(TexFont * txf, const char *TString, int len,
551 float z, float w, bool keep_pos)
552{
553 int i;
554
555 if(keep_pos) glPushMatrix();
556 for (i = 0; i < len; i++) {
557 txfRenderGlyphZW(txf, TString[i], z, w);
558 }
559 if(keep_pos) glPopMatrix();
560}
561
562/**************************************************************************/
563
564enum {
565 MONO, TOP_BOTTOM, LEFT_RIGHT, FOUR
566};
567
568/**************************************************************************/
569
570void txfRenderFancyString(TexFont * txf, char *TString, int len)
571{
572 TexGlyphVertexInfo *tgvi;
573 GLubyte c[4][3];
574 int mode = MONO;
575 int i;
576
577 for (i = 0; i < len; i++) {
578 if (TString[i] == 27) {
579 switch (TString[i + 1]) {
580 case 'M':
581 mode = MONO;
582 glColor3ubv((GLubyte *) & TString[i + 2]);
583 i += 4;
584 break;
585 case 'T':
586 mode = TOP_BOTTOM;
587 memcpy(c, &TString[i + 2], 6);
588 i += 7;
589 break;
590 case 'L':
591 mode = LEFT_RIGHT;
592 memcpy(c, &TString[i + 2], 6);
593 i += 7;
594 break;
595 case 'F':
596 mode = FOUR;
597 memcpy(c, &TString[i + 2], 12);
598 i += 13;
599 break;
600 }
601 } else {
602 switch (mode) {
603 case MONO:
604 txfRenderGlyph(txf, TString[i]);
605 break;
606 case TOP_BOTTOM:
607 tgvi = getTCVI(txf, TString[i]);
608 glBegin(GL_QUADS);
609 glColor3ubv(c[0]);
610 glTexCoord2fv(tgvi->t0);
611 glVertex2sv(tgvi->v0);
612 glTexCoord2fv(tgvi->t1);
613 glVertex2sv(tgvi->v1);
614 glColor3ubv(c[1]);
615 glTexCoord2fv(tgvi->t2);
616 glVertex2sv(tgvi->v2);
617 glTexCoord2fv(tgvi->t3);
618 glVertex2sv(tgvi->v3);
619 glEnd();
620 glTranslatef(tgvi->advance, 0.0, 0.0);
621 break;
622 case LEFT_RIGHT:
623 tgvi = getTCVI(txf, TString[i]);
624 glBegin(GL_QUADS);
625 glColor3ubv(c[0]);
626 glTexCoord2fv(tgvi->t0);
627 glVertex2sv(tgvi->v0);
628 glColor3ubv(c[1]);
629 glTexCoord2fv(tgvi->t1);
630 glVertex2sv(tgvi->v1);
631 glColor3ubv(c[1]);
632 glTexCoord2fv(tgvi->t2);
633 glVertex2sv(tgvi->v2);
634 glColor3ubv(c[0]);
635 glTexCoord2fv(tgvi->t3);
636 glVertex2sv(tgvi->v3);
637 glEnd();
638 glTranslatef(tgvi->advance, 0.0, 0.0);
639 break;
640 case FOUR:
641 tgvi = getTCVI(txf, TString[i]);
642 glBegin(GL_QUADS);
643 glColor3ubv(c[0]);
644 glTexCoord2fv(tgvi->t0);
645 glVertex2sv(tgvi->v0);
646 glColor3ubv(c[1]);
647 glTexCoord2fv(tgvi->t1);
648 glVertex2sv(tgvi->v1);
649 glColor3ubv(c[2]);
650 glTexCoord2fv(tgvi->t2);
651 glVertex2sv(tgvi->v2);
652 glColor3ubv(c[3]);
653 glTexCoord2fv(tgvi->t3);
654 glVertex2sv(tgvi->v3);
655 glEnd();
656 glTranslatef(tgvi->advance, 0.0, 0.0);
657 break;
658 }
659 }
660 }
661}
662
663/**************************************************************************/
664
665int txfInFont(TexFont * txf, int c)
666{
667 /* NOTE: No uppercase/lowercase substituion. */
668 if ((c >= txf->min_glyph) && (c < txf->min_glyph + txf->range)) {
669 if (txf->lut[c - txf->min_glyph]) {
670 return 1;
671 }
672 }
673 return 0;
674}
675
676/**************************************************************************/
677
678bool LoadDefaultFont( TString file)
679{
680 static const Exc_t _eh("GLTextNS::LoadFont ");
681
682 if(fgDefaultFont) {
683 txfUnloadFont(fgDefaultFont);
684 fgDefaultFont = 0;
685 }
686
687 fgDefaultFont = GLTextNS::txfLoadFont(file.Data());
688 if(fgDefaultFont != 0) {
689 txfEstablishTexture(fgDefaultFont, 0, GL_TRUE);
690 return true;
691 }
692 else {
693 throw(_eh + Form("Error loading font from file '%s': %s",
694 file.Data(), txfErrorString()));
695 }
696
697 return false;
698}
699
700} // end GLTextNS