1 /*
2 ==============================================================================
3 | GLF Library
4 | Version 1.4
5 |
6 | Author: Roman Podobedov
7 | Email: romka@ut.ee
8 | WEB: http://romka.demonews.com
9 | Release Date: 18 May 2001
10 |
11 | Copyright (C) 2000-2001, Romka Graphics
12 | This library is freely distributable without any license or permissions
13 | for non-commercial usage. You can use this library in any non-commercial
14 | program. In each program, where You use this library You should keep
15 | this header (author name and coordinates)!
16 | For commercial usage, please contact me: romka@ut.ee
17 ==============================================================================
18 */
19
20 //Not sure why this was needed. It seems to work fine without it on wx 2.8 and 2.9
21 //Including it causes issues with wx 2.9.0
22 //#if defined(WIN32)
23 //#include <windows.h>
24 //#endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
30 #include "glf.h"
31
32 /* ---------- Definitions and structures ----- */
33
Resampler()34 #define MAX_FONTS 256
35
36 /* Color structure */
37 struct color
38 {
39 float r, g, b, a;
40 };
41
42 /* One symbol of font */
43 struct one_symbol
~Resampler()44 {
45 unsigned char vertexs; /* Number of vertexs */
46 unsigned char facets; /* Number of facets */
47 unsigned char lines; /* Number of lines in symbol */
48
49 float *vdata; /* Pointer to Vertex data */
50 unsigned char *fdata; /* Pointer to Facets data */
51 unsigned char *ldata; /* Pointer to Line data */
52
53 float leftx; /* Smaller x coordinate */
54 float rightx; /* Right x coordinate */
55 float topy; /* Top y coordinate */
56 float bottomy; /* Bottom y coordinate */
57 };
58
59 /* Font structure */
60 struct glf_font
61 {
62 char font_name [97];
63 unsigned char sym_total; /* Total symbols in font */
64 struct one_symbol *symbols[256]; /* Pointers to symbols */
65 };
66
Reset(int inFreq,int outFreq,int num_channels)67 /* ------------- Main variables -------------- */
68
69 static float SymbolDist = 0.2f; /* Distance between symbols (Variable constant) */
70 static float SymbolDepth = 0.2f; /* Symbol Depth in 3D space (Variable constant) */
71 static float SpaceSize = 2.0f; /* Space size (Variable constant) */
72 static float RotateAngle = 0.0f; /* Rotate angle for string (vector font) */
73 static float RotateAngleB = 0.0f; /* Rotate angle for string (bitmap font) */
74
75 /* Array of font pointers, up to MAX_FONTS fonts can be loaded at once */
76 /* if (fonts[i] == NULL) then this font is not present in memory */
77
78 static struct glf_font *fonts[MAX_FONTS];
79 static int curfont; /* Index of current font pointer */
80 static char ap = GLF_CENTER; /* Anchor point */
81 static GLboolean m_string_center; /* String centering (vector fonts) */
82 static GLboolean m_bitmap_string_center; /* String centering (bitmap fonts) */
83
84 static GLuint m_direction; /* String direction (vector fonts) */
85
86 static char console_msg = GLF_NO;
87 static char texturing = GLF_NO;
88 static char contouring = GLF_NO;
89 static struct color contouring_color;
90
91 /* Console mode variables */
92 static int conWidth, conHeight; /* Console width and height */
93 static int conx = 0, cony = 0; /* Console current X and Y */
94 static char *conData; /* Console data */
95 static int conFont; /* Console font */
Push(const int16_t * samplesIn,int lengthIn,int16_t * samplesOut,int maxLen,int & outLen)96 static char conCursor = GLF_NO; /* Console cursor Enabled|Disabled */
97 static int conCursorBlink; /* Console cursor blink rate */
98 static int conCursorCount; /* Console cursor blink counter */
99 static char conCursorMode = GLF_NO; /* Console Cursor mode (on/off screen) */
100
101 /* ----------- Variables for bitmap font ------------- */
102 #define SEEK_SET_POS 4195
103
104 struct coord_rect
105 {
106 float x, y, width, height;
107 };
108
109 struct widths
110 {
111 float *width;
112 };
113
114 /* Constants */
115 static float sym_space=0.001f;
116
117 /* One font variables */
118 static struct coord_rect Symbols[256];
119 static GLboolean bmf_texturing;
120 static int bmf_curfont;
121 static GLuint bmf_texture[MAX_FONTS]; /* All fonts */
122 static GLuint bmf_mask[MAX_FONTS]; /* All fonts (masked) */
123 static char bmf_in_use[MAX_FONTS]; /* 1 - if font is used, 0 - otherwise */
124 static int list_base[MAX_FONTS];
125 static GLfloat m_max_height[MAX_FONTS]; /* Maximal height of each font */
126 static struct widths m_widths[MAX_FONTS]; /* Width of each symbols in each font */
127
128
129 /* Initialization of GLF library, should be called before use of library */
130 void glfInit()
131 {
132 int i;
133
134 for (i=0; i<MAX_FONTS; i++)
135 {
136 fonts[i] = NULL;
137 bmf_in_use[i] = 0;
138 m_max_height[i] = 0;
139 }
140
141 curfont = -1;
142 bmf_curfont = -1;
143 console_msg = GLF_NO;
144 ap = GLF_CENTER; /* Set anchor point to center of each symbol */
145 texturing = GLF_NO; /* By default texturing is NOT Enabled */
146 contouring = GLF_NO; /* By default contouring is NOT Enabled */
147 memset(&contouring_color, 0, sizeof(struct color));
148 conData = NULL;
149 glfSetConsoleParam(40, 20);
150 glfConsoleClear();
151 glfEnable(GLF_CONSOLE_CURSOR);
152 glfSetCursorBlinkRate(10);
153 glfStringCentering(GL_FALSE);
154 glfBitmapStringCentering(GL_FALSE);
155 glfStringDirection(GLF_LEFT);
156 }
157
158 /* Closing library usage */
159 void glfClose()
160 {
161 int i;
162
163 if (conData) {
164 free(conData);
165 conData = NULL;
166 }
167
168 for (i=0; i<MAX_FONTS; i++) glfUnloadFontD(i);
169 for (i=0; i<MAX_FONTS; i++) glfUnloadBMFFontD(i);
170 }
171
172 /*
173 | This function check that this machine is little endian
174 | Return value: 1 - little endian
175 | 0 - big endian
176 */
177 static int LittleEndian()
178 {
179 int endianTester = 1;
180 char *endianChar = 0;
181
182 endianChar = (char *)&endianTester;
183 if (*endianChar) return 1;
184 return 0;
185 }
186
187
188 /*
189 ---------------------------------------------------------------------------------
190 ------------------------ Work with vector fonts ---------------------------------
191 ---------------------------------------------------------------------------------
192 */
193
194 /*
195 | This function read font file and store information in memory
196 | Return: GLF_OK - if all OK
197 | Return: GLF_ERROR - if any error
198 */
199
200 static int ReadFont(const char *font_name, struct glf_font *glff) {
201
202 FILE *fontf;
203 char buffer[64];
204 int i, j;
205 unsigned char temp, code, verts, fcets, lns;
206 float tempfx, tempfy;
207 unsigned char *tp;
208 int LEndian; /* True if little endian machine */
209
210 fontf = fopen(font_name, "rb");
211 if (fontf == NULL) return GLF_ERROR;
212
213 fread(buffer, 1, 3, fontf);
214 buffer[3] = 0;
215 if (strcmp(buffer, "GLF")) {
216 /* If header is not "GLF" */
217 if (console_msg) printf("Error reading font file: incorrect file format\n");
218 return GLF_ERROR;
219 }
220
221 /* Check for machine type */
222 LEndian = LittleEndian();
223
224 fread(glff->font_name, 1, 96, fontf);
225 glff->font_name[96] = 0;
226
227 fread(&glff->sym_total, 1, 1, fontf); /* Read total symbols in font */
228
229 for (i=0; i<MAX_FONTS; i++) glff->symbols[i] = NULL;
230
231 for (i=0; i<28; i++) fread(&temp, 1, 1, fontf); /* Read unused data */
232
233 /* Now start to read font data */
234
235 for (i=0; i<glff->sym_total; i++)
236 {
237 fread(&code, 1, 1, fontf); /* Read symbol code */
238 fread(&verts, 1, 1, fontf); /* Read vertexs count */
239 fread(&fcets, 1, 1, fontf); /* Read facets count */
240 fread(&lns, 1, 1, fontf); /* Read lines count */
241
242 if (glff->symbols[code] != NULL)
243 {
244 if (console_msg) printf("Error reading font file: encountered symbols in font\n");
245 return GLF_ERROR;
246 }
247
248 glff->symbols[code] = (struct one_symbol *)malloc(sizeof(struct one_symbol));
249 glff->symbols[code]->vdata = (float *)malloc(8*verts);
250 glff->symbols[code]->fdata = (unsigned char *)malloc(3*fcets);
251 glff->symbols[code]->ldata = (unsigned char *)malloc(lns);
252
253 glff->symbols[code]->vertexs = verts;
254 glff->symbols[code]->facets = fcets;
255 glff->symbols[code]->lines = lns;
256
257 /* Read vertexs data */
258 glff->symbols[code]->leftx = 10;
259 glff->symbols[code]->rightx = -10;
260 glff->symbols[code]->topy = 10;
261 glff->symbols[code]->bottomy = -10;
262
263 for (j=0; j<verts; j++)
264 {
265 fread(&tempfx, 4, 1, fontf);
266 fread(&tempfy, 4, 1, fontf);
267
268 /* If machine is bigendian -> swap low and high words in
269 tempfx and tempfy */
270 if (!LEndian) {
271 tp = (unsigned char *)&tempfx;
272 temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
273 temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
274 tp = (unsigned char *)&tempfy;
275 temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
276 temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
277 }
278 glff->symbols[code]->vdata[j*2] = tempfx;
279 glff->symbols[code]->vdata[j*2+1] = tempfy;
280
281 if (tempfx < glff->symbols[code]->leftx) glff->symbols[code]->leftx = tempfx;
282 if (tempfx > glff->symbols[code]->rightx) glff->symbols[code]->rightx = tempfx;
283 if (tempfy < glff->symbols[code]->topy) glff->symbols[code]->topy = tempfy;
284 if (tempfy > glff->symbols[code]->bottomy) glff->symbols[code]->bottomy = tempfy;
285 }
286 for (j=0; j<fcets; j++)
287 fread(&glff->symbols[code]->fdata[j*3], 1, 3, fontf);
288 for (j=0; j<lns; j++)
289 fread(&glff->symbols[code]->ldata[j], 1, 1, fontf);
290 }
291 fclose(fontf);
292 return GLF_OK;
293 }
294
295
296 /*
297 | Function loads font to memory from file
298 | Return value: GLF_ERROR - if error
299 | >=0 - returned font descriptor (load success)
300 */
301 int glfLoadFont(const char *font_name)
302 {
303 int i;
304 char flag; /* Temporary flag */
305
306 /* First we find free font descriptor */
307 flag = 0; /* Descriptor not found yet */
308 for (i=0; i<MAX_FONTS; i++)
309 if (fonts[i] == NULL)
310 {
311 /* Initialize this font */
312 fonts[i] = (struct glf_font *)malloc(sizeof(struct glf_font));
313 flag = 1;
314 break;
315 }
316
317 if (!flag) return GLF_ERROR; /* Free font not found */
318 if (ReadFont(font_name, fonts[i]) == GLF_OK)
319 {
320 curfont = i; /* Set curfont to just loaded font */
321 return i;
322 }
323
324 if (fonts[i] != NULL)
325 {
326 free(fonts[i]);
327 fonts[i] = NULL;
328 }
329 return GLF_ERROR;
330 }
331
332 /*
333 | Unload current font from memory
334 | Return value: GLF_OK - if all OK
335 | GLF_ERROR - if error
336 */
337 int glfUnloadFont()
338 {
339 int i;
340
341 if ((curfont<0) || (fonts[curfont] == NULL)) return GLF_ERROR;
342
343 for (i=0; i<256; i++)
344 {
345 if (fonts[curfont]->symbols[i] != NULL)
346 {
347 free(fonts[curfont]->symbols[i]->vdata);
348 free(fonts[curfont]->symbols[i]->fdata);
349 free(fonts[curfont]->symbols[i]->ldata);
350 free(fonts[curfont]->symbols[i]);
351 }
352 }
353
354 free(fonts[curfont]);
355 fonts[curfont] = NULL;
356 curfont = -1;
357 return GLF_OK;
358 }
359
360 /* Unload font by font descriptor */
361 int glfUnloadFontD(int font_descriptor)
362 {
363 int temp;
364
365 if ((font_descriptor < 0) || (fonts[font_descriptor] == NULL)) return GLF_ERROR;
366
367 temp = curfont;
368 curfont = font_descriptor;
369 glfUnloadFont();
370 if (temp != font_descriptor) curfont = temp;
371 else curfont = -1;
372 return GLF_OK;
373 }
374
375 void glfDrawWiredSymbol(char s)
376 {
377 int i, cur_line;
378 float *tvp; /* temporary vertex pointer */
379 float x, y;
380
381 if ((curfont < 0) || (fonts[curfont] == NULL)) return;
382 if (fonts[curfont]->symbols[s] == NULL) return;
383
384 glBegin(GL_LINE_LOOP);
385 tvp = fonts[curfont]->symbols[s]->vdata;
386 cur_line = 0;
387 for (i=0; i<fonts[curfont]->symbols[s]->vertexs; i++)
388 {
389 x = *tvp++;
390 y = *tvp++;
391 glVertex2f(x, y);
392 if (fonts[curfont]->symbols[s]->ldata[cur_line] == i)
393 {
394 glEnd();
395 cur_line++;
396 if (cur_line < fonts[curfont]->symbols[s]->lines) glBegin(GL_LINE_LOOP);
397 else break; /* No more lines */
398 }
399 }
400 }
401
402 /* Draw wired symbol by font_descriptor */
403 void glfDrawWiredSymbolF(int font_descriptor, char s)
404 {
405 int temp;
406
407 temp = curfont;
408 curfont = font_descriptor;
409 glfDrawWiredSymbol(s);
410 curfont = temp;
411 }
412
413 static void DrawString(const char *s, void (*funct) (char s))
414 {
415 int i;
416 float sda, sdb;
417 float distance;
418
419 if (!s) return;
420 if (!*s) return;
421 if (curfont == -1) return;
422
423 /* Calculate correction (if string centering enabled) */
424 if (m_string_center)
425 {
426 distance = 0;
427 for (i=0; i<(int)strlen(s); i++)
428 {
429 if ((fonts[curfont]->symbols[s[i]] == NULL) || (s[i] == ' '))
430 {
431 if (m_direction == GLF_LEFT || m_direction == GLF_UP) distance += SpaceSize;
432 else distance -= SpaceSize;
433 }
434 else {
435 if (i < ((int)strlen(s)-1)) {
436 if (s[i+1] == ' ')
437 {
438 if (m_direction == GLF_LEFT || m_direction == GLF_UP) distance += SymbolDist;
439 else distance -= SymbolDist;
440 }
441 else
442 {
443 if (fonts[curfont]->symbols[s[i+1]] == NULL) continue;
444
445 if (m_direction == GLF_LEFT || m_direction == GLF_RIGHT)
446 {
447 sda = (float)fabs(fonts[curfont]->symbols[s[i]]->rightx);
448 sdb = (float)fabs(fonts[curfont]->symbols[s[i+1]]->leftx);
449 if (m_direction == GLF_LEFT) distance += sda+sdb+SymbolDist;
450 else distance -= sda+sdb+SymbolDist;
451 }
452 else
453 {
454 sda = (float)fabs(fonts[curfont]->symbols[s[i]]->topy);
455 sdb = (float)fabs(fonts[curfont]->symbols[s[i]]->bottomy);
456 if (m_direction == GLF_DOWN) distance -= sda+sdb+SymbolDist;
457 else distance += sda+sdb+SymbolDist;
458 }
459 }
460 }
461 }
462 }
463 }
464
465 glPushMatrix();
466
467 /* Rotate if needed */
468 if (RotateAngle != 0.0f) glRotatef(RotateAngle, 0, 0, 1);
469
470 /* Correct string position */
471 if (m_string_center)
472 {
473 switch (m_direction)
474 {
475 case GLF_LEFT : glTranslatef(-distance/2, 0, 0); break;
476 case GLF_RIGHT : glTranslatef(distance/2, 0, 0); break;
477 case GLF_UP : glTranslatef(0, distance/2, 0); break;
478 case GLF_DOWN : glTranslatef(0, -distance/2, 0); break;
479 }
480 }
481 else if (s[0] != ' ')
482 {
483 switch (m_direction)
484 {
485 case GLF_LEFT : glTranslatef(-(1-(float)fabs(fonts[curfont]->symbols[s[0]]->leftx)), 0, 0); break;
486 case GLF_RIGHT : glTranslatef((1-(float)fabs(fonts[curfont]->symbols[s[0]]->rightx)), 0, 0); break;
487 case GLF_UP : glTranslatef(0, (1-(float)fabs(fonts[curfont]->symbols[s[0]]->topy)), 0); break;
488 case GLF_DOWN : glTranslatef(0, -(1-(float)fabs(fonts[curfont]->symbols[s[0]]->bottomy)), 0); break;
489 }
490 }
491
492 /* Start to draw our string */
493 for (i=0; i<(int)strlen(s); i++)
494 {
495 if (s[i] != ' ') (*funct) (s[i]);
496 if ((fonts[curfont]->symbols[s[i]] == NULL) || (s[i] == ' '))
497 {
498 switch (m_direction)
499 {
500 case GLF_LEFT : glTranslatef(SpaceSize, 0, 0); break;
501 case GLF_RIGHT : glTranslatef(-SpaceSize, 0, 0); break;
502 case GLF_UP : glTranslatef(0, SpaceSize, 0); break;
503 case GLF_DOWN : glTranslatef(0, -SpaceSize, 0); break;
504 }
505 }
506 else {
507 if (i < ((int)strlen(s)-1)) {
508 if (s[i+1] == ' ')
509 {
510 switch (m_direction)
511 {
512 case GLF_LEFT : glTranslatef(SymbolDist, 0, 0); break;
513 case GLF_RIGHT : glTranslatef(-SymbolDist, 0, 0); break;
514 case GLF_UP : glTranslatef(0, SymbolDist, 0); break;
515 case GLF_DOWN : glTranslatef(0, -SymbolDist, 0); break;
516 }
517 }
518 else
519 {
520 if (fonts[curfont]->symbols[s[i+1]] == NULL) continue;
521
522 if (m_direction == GLF_LEFT || m_direction == GLF_RIGHT)
523 {
524 if (m_direction == GLF_LEFT)
525 {
526 sda = (float)fabs(fonts[curfont]->symbols[s[i]]->rightx);
527 sdb = (float)fabs(fonts[curfont]->symbols[s[i+1]]->leftx);
528 }
529 else
530 {
531 sda = (float)fabs(fonts[curfont]->symbols[s[i+1]]->rightx);
532 sdb = (float)fabs(fonts[curfont]->symbols[s[i]]->leftx);
533 }
534
535 if (m_direction == GLF_LEFT) glTranslatef(sda+sdb+SymbolDist, 0, 0);
536 else glTranslatef(-(sda+sdb+SymbolDist), 0, 0);
537 }
538 else
539 {
540 if (m_direction == GLF_DOWN)
541 {
542 sda = (float)fabs(fonts[curfont]->symbols[s[i]]->topy);
543 sdb = (float)fabs(fonts[curfont]->symbols[s[i+1]]->bottomy);
544 }
545 else
546 {
547 sda = (float)fabs(fonts[curfont]->symbols[s[i+1]]->topy);
548 sdb = (float)fabs(fonts[curfont]->symbols[s[i]]->bottomy);
549 }
550
551 if (m_direction == GLF_DOWN) glTranslatef(0, -(sda+sdb+SymbolDist), 0);
552 else glTranslatef(0, sda+sdb+SymbolDist, 0);
553 }
554
555 }
556 }
557 }
558 }
559 glPopMatrix();
560 }
561
562 void glfDrawWiredString(const char *s)
563 {
564 DrawString(s, &glfDrawWiredSymbol);
565 }
566
567 /* Draw wired string by font_descriptor */
568 void glfDrawWiredStringF(int font_descriptor, char *s)
569 {
570 int temp;
571
572 temp = curfont;
573 curfont = font_descriptor;
574 DrawString(s, &glfDrawWiredSymbol);
575 curfont = temp;
576 }
577
578 void glfDrawSolidSymbol(char s)
579 {
580 unsigned char *b; /* Face pointer */
581 float *vp; /* Vertex pointer */
582 int i, j;
583 float x, y;
584 float temp_color[4];
585
586 if ((curfont<0) || (fonts[curfont] == NULL)) return;
587
588 if (fonts[curfont]->symbols[s] == NULL) return;
589
590 b = fonts[curfont]->symbols[s]->fdata;
591 vp = fonts[curfont]->symbols[s]->vdata;
592
593 glBegin(GL_TRIANGLES);
594 for (i=0; i<fonts[curfont]->symbols[s]->facets; i++)
595 {
596 for (j=0; j<3; j++)
597 {
598 x = vp[*b*2];
599 y = vp[*b*2+1];
600 if (texturing == GLF_YES) glTexCoord2f((x+1)/2, (y+1)/2);
601 glVertex2f(x, y);
602 b++;
603 }
604 }
605 glEnd();
606
607 /* Draw contour, if enabled */
608 if (contouring == GLF_YES)
609 {
610 glGetFloatv(GL_CURRENT_COLOR, temp_color);
611 glColor4f(contouring_color.r, contouring_color.g, contouring_color.b, contouring_color.a);
612 glfDrawWiredSymbol(s);
613 glColor4fv(temp_color);
614 }
615 }
616
617 /* Draw solid symbol by font_descriptor */
618 void glfDrawSolidSymbolF(int font_descriptor, char s)
619 {
620 int temp;
621
622 temp = curfont;
623 curfont = font_descriptor;
624 glfDrawSolidSymbol(s);
625 curfont = temp;
626 }
627
628 void glfDrawSolidString(const char *s)
629 {
630 DrawString(s, &glfDrawSolidSymbol);
631 }
632
633 /* Draw solid string by font_descriptor */
634 void glfDrawSolidStringF(int font_descriptor, char *s)
635 {
636 int temp;
637
638 temp = curfont;
639 curfont = font_descriptor;
640 DrawString(s, &glfDrawSolidSymbol);
641 curfont = temp;
642 }
643
644
645 /* ------------ 3D Wired text drawing ---------------------- */
646
647 void glfDraw3DWiredSymbol(char s)
648 {
649 int i, cur_line;
650 float *tvp; /* temp vertex pointer */
651 float x, y;
652
653 if ((curfont<0) || (fonts[curfont] == NULL)) return;
654 if (fonts[curfont]->symbols[(int)s] == NULL) return;
655
656 /* Draw front symbol */
657 glBegin(GL_LINE_LOOP);
658 tvp = fonts[curfont]->symbols[s]->vdata;
659 cur_line = 0;
660 for (i=0; i<fonts[curfont]->symbols[s]->vertexs; i++)
661 {
662 x = *tvp;
663 tvp++;
664 y = *tvp;
665 tvp++;
666 glVertex3f(x, y, 1);
667 if (fonts[curfont]->symbols[s]->ldata[cur_line] == i)
668 {
669 glEnd();
670 cur_line++;
671 if (cur_line < fonts[curfont]->symbols[s]->lines) glBegin(GL_LINE_LOOP);
672 else break; /* No more lines */
673 }
674 }
675
676 /* Draw back symbol */
677 glBegin(GL_LINE_LOOP);
678 tvp = fonts[curfont]->symbols[s]->vdata;
679 cur_line = 0;
680 for (i=0; i<fonts[curfont]->symbols[s]->vertexs; i++)
681 {
682 x = *tvp;
683 tvp++;
684 y = *tvp;
685 tvp++;
686 glVertex3f(x, y, 1+SymbolDepth);
687 if (fonts[curfont]->symbols[s]->ldata[cur_line] == i)
688 {
689 glEnd();
690 cur_line++;
691 if (cur_line < fonts[curfont]->symbols[s]->lines) glBegin(GL_LINE_LOOP);
692 else break; /* No more lines */
693 }
694 }
695
696 /* Draw lines between back and front symbols */
697 glBegin(GL_LINES);
698 tvp = fonts[curfont]->symbols[s]->vdata;
699 for (i=0; i<fonts[curfont]->symbols[s]->vertexs; i++)
700 {
701 x = *tvp;
702 tvp++;
703 y = *tvp;
704 tvp++;
705 glVertex3f(x, y, 1);
706 glVertex3f(x, y, 1+SymbolDepth);
707 }
708 glEnd();
709 }
710
711 /* Draw 3D wired symbol by font_descriptor */
712 void glfDraw3DWiredSymbolF(int font_descriptor, char s)
713 {
714 int temp;
715
716 temp = curfont;
717 curfont = font_descriptor;
718 glfDraw3DWiredSymbol(s);
719 curfont = temp;
720 }
721
722 void glfDraw3DWiredString(char *s)
723 {
724 DrawString(s, &glfDraw3DWiredSymbol);
725 }
726
727 /* Draw 3D wired string by font_descriptor */
728 void glfDraw3DWiredStringF(int font_descriptor, char *s)
729 {
730 int temp;
731
732 temp = curfont;
733 curfont = font_descriptor;
734 DrawString(s, &glfDraw3DWiredSymbol);
735 curfont = temp;
736 }
737
738 /* ------------ 3D Solid text drawing ---------------------- */
739
740 void glfDraw3DSolidSymbol(char s)
741 {
742 int i, j, cur_line, flag;
743 float x, y, bx, by;
744 unsigned char *b; /* Face pointer */
745 float *vp; /* Vertex pointer */
746 float *tvp; /* temp vertex pointer */
747 float temp_color[4];
748 GLboolean light_temp;
749
750 if ((curfont<0) || (fonts[curfont] == NULL)) return;
751 if (fonts[curfont]->symbols[(int)s] == NULL) return;
752
753 b = fonts[curfont]->symbols[s]->fdata;
754 vp = fonts[curfont]->symbols[s]->vdata;
755
756 glBegin(GL_TRIANGLES);
757 glNormal3f(0, 0, 1);
758 for (i=0; i<fonts[curfont]->symbols[s]->facets; i++)
759 {
760 b += 2;
761 for (j=0; j<3; j++)
762 {
763 x = vp[*b*2];
764 y = vp[*b*2+1];
765 glVertex3f(x, y, 1+SymbolDepth);
766 b--;
767 }
768 b += 4;
769 }
770 glEnd();
771
772 b = fonts[curfont]->symbols[s]->fdata;
773 vp = fonts[curfont]->symbols[s]->vdata;
774
775 glBegin(GL_TRIANGLES);
776 glNormal3f(0, 0, -1);
777 for (i=0; i<fonts[curfont]->symbols[s]->facets; i++)
778 {
779 for (j=0; j<3; j++)
780 {
781 x = vp[*b*2];
782 y = vp[*b*2+1];
783 glVertex3f(x, y, 1);
784 b++;
785 }
786 }
787 glEnd();
788
789 flag = 0;
790 glBegin(GL_QUAD_STRIP);
791 tvp = fonts[curfont]->symbols[s]->vdata;
792 cur_line = 0;
793 for (i=0; i<fonts[curfont]->symbols[s]->vertexs; i++)
794 {
795 x = *tvp;
796 tvp++;
797 y = *tvp;
798 tvp++;
799 if (!flag)
800 {
801 bx = x;
802 by = y;
803 flag = 1;
804 }
805 glNormal3f(x, y, 0);
806 glVertex3f(x, y, 1);
807 glVertex3f(x, y, 1+SymbolDepth);
808 if (fonts[curfont]->symbols[s]->ldata[cur_line] == i)
809 {
810 glVertex3f(bx, by, 1);
811 glVertex3f(bx, by, 1+SymbolDepth);
812 flag = 0;
813 glEnd();
814 cur_line++;
815 if (cur_line < fonts[curfont]->symbols[s]->lines) glBegin(GL_QUAD_STRIP);
816 else break; /* No more lines */
817 }
818 }
819
820 /* Draw contour, if enabled */
821 if (contouring == GLF_YES)
822 {
823 glGetBooleanv(GL_LIGHTING, &light_temp);
824 glDisable(GL_LIGHTING);
825 glGetFloatv(GL_CURRENT_COLOR, temp_color);
826 glColor4f(contouring_color.r, contouring_color.g, contouring_color.b, contouring_color.a);
827 glfDraw3DWiredSymbol(s);
828 glColor4fv(temp_color);
829 if (light_temp) glEnable(GL_LIGHTING);
830 }
831 }
832
833 /* Draw 3D solid symbol by font_descriptor */
834 void glfDraw3DSolidSymbolF(int font_descriptor, char s)
835 {
836 int temp;
837
838 temp = curfont;
839 curfont = font_descriptor;
840 glfDraw3DSolidSymbol(s);
841 curfont = temp;
842 }
843
844 void glfDraw3DSolidString(char *s)
845 {
846 DrawString(s, &glfDraw3DSolidSymbol);
847 }
848
849 /* Draw 3D solid string by font_descriptor */
850 void glfDraw3DSolidStringF(int font_descriptor, char *s)
851 {
852 int temp;
853
854 temp = curfont;
855 curfont = font_descriptor;
856 DrawString(s, &glfDraw3DSolidSymbol);
857 curfont = temp;
858 }
859
860 /* Get the size a string will have on screen */
861 void glfGetStringBoundsF(int fd, char *s, float *minx, float *miny, float *maxx, float *maxy)
862 {
863 struct glf_font *font;
864 int i;
865 float sda, sdb, cw = 0, minxx = 10;
866 float top = 10, bottom = -10;
867
868 if (fd < 0 || fd > (MAX_FONTS-1)) return;
869 font = fonts[fd];
870
871 if (font == NULL) return;
872
873 if (font->symbols[s[0]])
874 minxx = font->symbols[s[0]]->leftx;
875 else
876 minxx = 0.0;
877
878 for (i=0; i<(int)strlen(s); i++)
879 {
880 if ((font->symbols[s[i]] == NULL) || (s[i] == ' '))
881 cw += SpaceSize;
882 else
883 {
884 sdb = -font->symbols[(int)s[i]]->leftx;
885 sda = font->symbols[(int)s[i]]->rightx;
886
887 cw += sda+sdb+SymbolDist;
888
889 /* Update top/bottom bounds */
890 if (font->symbols[(int)s[i]]->bottomy > bottom)
891 bottom = font->symbols[(int)s[i]]->bottomy;
892
893 if (font->symbols[(int)s[i]]->topy < top)
894 top = font->symbols[(int)s[i]]->topy;
895 }
896 }
897
898 cw += minxx;
899
900 if ((maxx) && (maxy))
901 {
902 *maxx = cw;
903 *maxy = bottom;
904 }
905
906 if ((minx) && (miny))
907 {
908 *minx = minxx;
909 *miny = top;
910 }
911 }
912
913 void glfGetStringBounds(char *s, float *minx, float *miny, float *maxx, float *maxy)
914 {
915 glfGetStringBoundsF(curfont, s, minx, miny, maxx, maxy);
916 }
917
918 void glfSetSymbolSpace(float sp)
919 {
920 SymbolDist = sp;
921 }
922
923 float glfGetSymbolSpace()
924 {
925 return SymbolDist;
926 }
927
928 void glfSetSpaceSize(float sp)
929 {
930 SpaceSize = sp;
931 }
932
933 float glfGetSpaceSize()
934 {
935 return SpaceSize;
936 }
937
938 void glfSetSymbolDepth(float dpth)
939 {
940 SymbolDepth = dpth;
941 }
942
943 float glfGetSymbolDepth()
944 {
945 return SymbolDepth;
946 }
947
948 int glfSetCurrentFont(int Font_Descriptor)
949 {
950 if ((Font_Descriptor < 0) || (fonts[Font_Descriptor] == NULL)) return GLF_ERROR;
951
952 curfont = Font_Descriptor;
953 return GLF_OK;
954 }
955
956 int glfGetCurrentFont()
957 {
958 return curfont;
959 }
960
961 void glfSetAnchorPoint(int anchp)
962 {
963 if ((anchp >= GLF_LEFT_UP) && (anchp <= GLF_RIGHT_DOWN))
964 ap = anchp;
965 }
966
967 void glfSetContourColor(float r, float g, float b, float a)
968 {
969 contouring_color.r = r;
970 contouring_color.g = g;
971 contouring_color.b = b;
972 contouring_color.a = a;
973 }
974
975 void glfEnable(int what)
976 {
977 switch (what)
978 {
979 case GLF_CONSOLE_MESSAGES: console_msg = GLF_YES; break;
980 case GLF_TEXTURING: texturing = GLF_YES; break;
981 case GLF_CONSOLE_CURSOR: conCursor = GLF_YES; break;
982 case GLF_CONTOURING: contouring = GLF_YES; break;
983 }
984 }
985
986 void glfDisable(int what)
987 {
988 switch (what)
989 {
990 case GLF_CONSOLE_MESSAGES: console_msg = GLF_NO; break;
991 case GLF_TEXTURING: texturing = GLF_NO; break;
992 case GLF_CONSOLE_CURSOR: conCursor = GLF_NO; break;
993 case GLF_CONTOURING: contouring = GLF_NO; break;
994 }
995 }
996
997 /* ---------------- Console functions ---------------------- */
998
999 void glfSetConsoleParam(int width, int height)
1000 {
1001 if (conData) free(conData);
1002
1003 conWidth = width;
1004 conHeight = height;
1005 conData = (char *)malloc(width*height);
1006 glfConsoleClear();
1007 }
1008
1009 int glfSetConsoleFont(int Font_Descriptor)
1010 {
1011 if ((Font_Descriptor < 0) || (fonts[Font_Descriptor] == NULL)) return GLF_ERROR;
1012
1013 conFont = Font_Descriptor;
1014 return GLF_OK;
1015 }
1016
1017 void glfConsoleClear()
1018 {
1019 memset(conData, 0, conWidth*conHeight);
1020 conx = 0;
1021 cony = 0;
1022 }
1023
1024 void glfPrint(char *s, int lenght)
1025 {
1026 int i;
1027
1028 for (i=0; i<lenght; i++)
1029 {
1030 if (s[i] > 31)
1031 {
1032 conData[cony*conWidth+conx] = s[i];
1033 conx++;
1034 } else
1035 if (s[i] == '\n') conx = conWidth;
1036 if (conx >= conWidth)
1037 {
1038 conx = 0;
1039 cony++;
1040 if (cony >= conHeight)
1041 {
1042 /* Shift all console contents up */
1043 memcpy(conData, &conData[conWidth], conWidth*(conHeight-1));
1044 /* Fill bottom line by spaces */
1045 memset(&conData[conWidth*(conHeight-1)], 0, conWidth);
1046 cony = conHeight-1;
1047 }
1048 }
1049 }
1050 }
1051
1052 void glfPrintString(char *s)
1053 {
1054 glfPrint(s, strlen(s));
1055 }
1056
1057 void glfPrintChar(char s)
1058 {
1059 glfPrint(&s, 1);
1060 }
1061
1062 void glfConsoleDraw()
1063 {
1064 int i, j;
1065 char s[512];
1066
1067 for (i=0; i<conHeight; i++)
1068 {
1069 memcpy(s, &conData[i*conWidth], conWidth);
1070 s[conWidth] = 0;
1071 if ((conCursor == GLF_YES) && (i == cony))
1072 {
1073 conCursorCount--;
1074 if (conCursorCount < 0)
1075 {
1076 conCursorCount = conCursorBlink;
1077 if (conCursorMode == GLF_YES) conCursorMode = GLF_NO;
1078 else conCursorMode = GLF_YES;
1079 }
1080
1081 if (conCursorMode == GLF_YES)
1082 for (j=0; j<conWidth; j++)
1083 {
1084 if (!s[j])
1085 {
1086 s[j] = '_'; /* Draw cursor */
1087 s[j+1] = 0;
1088 break;
1089 }
1090 }
1091 }
1092 glfDrawSolidStringF(conFont, s);
1093 glTranslatef(0, -2, 0);
1094 }
1095 }
1096
1097 void glfSetCursorBlinkRate(int Rate)
1098 {
1099 if (Rate > 0)
1100 {
1101 conCursorBlink = Rate;
1102 conCursorCount = Rate;
1103 conCursorMode = GLF_YES;
1104 }
1105 }
1106
1107 /* Set string centering for vector fonts */
1108 void glfStringCentering(GLboolean center)
1109 {
1110 m_string_center = center;
1111 }
1112
1113 /* String direction for vector font (GLF_LEFT, GLF_RIGHT, GLF_UP, GLF_DOWN) */
1114 /* GLF_LEFT by default */
1115 void glfStringDirection(GLuint direction)
1116 {
1117 if (direction == GLF_LEFT || direction == GLF_RIGHT ||
1118 direction == GLF_UP || direction == GLF_DOWN) m_direction = direction;
1119 }
1120
1121 /* Get current text direction */
1122 GLuint glfGetStringDirection()
1123 {
1124 return m_direction;
1125 }
1126
1127
1128 /* Get string centering for vector fonts */
1129 GLboolean glfGetStringCentering()
1130 {
1131 return m_string_center;
1132 }
1133
1134 /* Set rotate angle for vector fonts */
1135 void glfSetRotateAngle(float angle)
1136 {
1137 RotateAngle = angle;
1138 }
1139
1140
1141 /*
1142 ---------------------------------------------------------------------------------
1143 ------------------------ Work with bitmapped fonts ------------------------------
1144 ---------------------------------------------------------------------------------
1145 */
1146
1147
1148 /* Some color conversions */
1149 static void bwtorgba(unsigned char *b,unsigned char *l,int n)
1150 {
1151 while (n--)
1152 {
1153 l[0] = *b; l[1] = *b;
1154 l[2] = *b; l[3] = 0xff;
1155 l += 4; b++;
1156 }
1157 }
1158
1159 static void latorgba(unsigned char *b, unsigned char *a,unsigned char *l,int n)
1160 {
1161 while(n--)
1162 {
1163 l[0] = *b; l[1] = *b;
1164 l[2] = *b; l[3] = *a;
1165 l += 4; b++; a++;
1166 }
1167 }
1168
1169 static void rgbtorgba(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *l,int n)
1170 {
1171 while(n--)
1172 {
1173 l[0] = r[0]; l[1] = g[0];
1174 l[2] = b[0]; l[3] = 0xff;
1175 l += 4; r++; g++; b++;
1176 }
1177 }
1178
1179 static void rgbatorgba(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *a,unsigned char *l,int n)
1180 {
1181 while(n--)
1182 {
1183 l[0] = r[0]; l[1] = g[0];
1184 l[2] = b[0]; l[3] = a[0];
1185 l += 4; r++; g++; b++; a++;
1186 }
1187 }
1188
1189 typedef struct _ImageRec
1190 {
1191 unsigned short imagic;
1192 unsigned short type;
1193 unsigned short dim;
1194 unsigned short xsize, ysize, zsize;
1195 unsigned int min, max;
1196 unsigned int wasteBytes;
1197 char name[80];
1198 unsigned long colorMap;
1199 FILE *file;
1200 unsigned char *tmp, *tmpR, *tmpG, *tmpB;
1201 unsigned long rleEnd;
1202 unsigned int *rowStart;
1203 int *rowSize;
1204 } ImageRec;
1205
1206 static void ConvertShort(unsigned short *array, long length)
1207 {
1208 unsigned b1, b2;
1209 unsigned char *ptr;
1210
1211 ptr = (unsigned char *)array;
1212 while (length--) {
1213 b1 = *ptr++;
1214 b2 = *ptr++;
1215 *array++ = (b1 << 8) | (b2);
1216 }
1217 }
1218
1219 static void ConvertLong(unsigned *array, long length)
1220 {
1221 unsigned b1, b2, b3, b4;
1222 unsigned char *ptr;
1223
1224 ptr = (unsigned char *)array;
1225 while (length--)
1226 {
1227 b1 = *ptr++;
1228 b2 = *ptr++;
1229 b3 = *ptr++;
1230 b4 = *ptr++;
1231 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
1232 }
1233 }
1234
1235 /* Open RGB Image */
1236 static ImageRec *ImageOpen(FILE *f) {
1237
1238 ImageRec *image;
1239 int swapFlag;
1240 int x;
1241
1242 swapFlag = LittleEndian();
1243
1244 image = (ImageRec *)malloc(sizeof(ImageRec));
1245 if (image == NULL) {
1246 fprintf(stderr, "Out of memory!\n");
1247 exit(1);
1248 }
1249
1250 image->file = f;
1251
1252 fread(image, 1, 12, image->file);
1253
1254 if (swapFlag) ConvertShort(&image->imagic, 6);
1255
1256 image->tmp = (unsigned char *)malloc(image->xsize*256);
1257 image->tmpR = (unsigned char *)malloc(image->xsize*256);
1258 image->tmpG = (unsigned char *)malloc(image->xsize*256);
1259 image->tmpB = (unsigned char *)malloc(image->xsize*256);
1260 if (image->tmp == NULL || image->tmpR == NULL || image->tmpG == NULL ||
1261 image->tmpB == NULL) {
1262 fprintf(stderr, "Out of memory!\n");
1263 exit(1);
1264 }
1265
1266 if ((image->type & 0xFF00) == 0x0100) {
1267 x = image->ysize * image->zsize * sizeof(unsigned);
1268 image->rowStart = (unsigned *)malloc(x);
1269 image->rowSize = (int *)malloc(x);
1270 if (image->rowStart == NULL || image->rowSize == NULL)
1271 {
1272 fprintf(stderr, "Out of memory!\n");
1273 exit(1);
1274 }
1275 image->rleEnd = 512 + (2 * x);
1276 fseek(image->file, 512+SEEK_SET_POS, SEEK_SET);
1277 fread(image->rowStart, 1, x, image->file);
1278 fread(image->rowSize, 1, x, image->file);
1279 if (swapFlag)
1280 {
1281 ConvertLong(image->rowStart, x/(int)sizeof(unsigned));
1282 ConvertLong((unsigned *)image->rowSize, x/(int)sizeof(int));
1283 }
1284 } else {
1285 image->rowStart = NULL;
1286 image->rowSize = NULL;
1287 }
1288 return image;
1289 }
1290
1291 /* Close Image and free data */
1292 static void ImageClose(ImageRec *image)
1293 {
1294 free(image->tmp);
1295 free(image->tmpR);
1296 free(image->tmpG);
1297 free(image->tmpB);
1298 free(image->rowSize);
1299 free(image->rowStart);
1300 free(image);
1301 }
1302
1303 /* Pixels row decoding (if used RLE encoding) */
1304 static void ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z)
1305 {
1306 unsigned char *iPtr, *oPtr, pixel;
1307 int count;
1308
1309 if ((image->type & 0xFF00) == 0x0100)
1310 {
1311 fseek(image->file, (long)image->rowStart[y+z*image->ysize]+SEEK_SET_POS, SEEK_SET);
1312 fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize], image->file);
1313
1314 iPtr = image->tmp;
1315 oPtr = buf;
1316 for (;;)
1317 {
1318 pixel = *iPtr++;
1319 count = (int)(pixel & 0x7F);
1320 if (!count) return;
1321 if (pixel & 0x80) while (count--) *oPtr++ = *iPtr++;
1322 else
1323 {
1324 pixel = *iPtr++;
1325 while (count--) *oPtr++ = pixel;
1326 }
1327 }
1328 }
1329 else
1330 {
1331 fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize)+SEEK_SET_POS, SEEK_SET);
1332 fread(buf, 1, image->xsize, image->file);
1333 }
1334 }
1335
1336 /* Read SGI (RGB) Image from file */
1337 static unsigned *read_texture(FILE *f, int *width, int *height, int *components)
1338 {
1339 unsigned *base, *lptr;
1340 unsigned char *rbuf, *gbuf, *bbuf, *abuf;
1341 ImageRec *image;
1342 int y;
1343
1344 image = ImageOpen(f);
1345
1346 if (!image) return NULL;
1347 (*width) = image->xsize;
1348 (*height) = image->ysize;
1349 (*components) = image->zsize;
1350
1351 base = (unsigned *)malloc(image->xsize*image->ysize*sizeof(unsigned));
1352 rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
1353 gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
1354 bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
1355 abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
1356
1357 if(!base || !rbuf || !gbuf || !bbuf) return NULL;
1358 lptr = base;
1359 for (y=0; y<image->ysize; y++)
1360 {
1361 if(image->zsize >= 4)
1362 {
1363 ImageGetRow(image, rbuf, y, 0);
1364 ImageGetRow(image, gbuf, y, 1);
1365 ImageGetRow(image, bbuf, y, 2);
1366 ImageGetRow(image, abuf, y, 3);
1367 rgbatorgba(rbuf,gbuf,bbuf,abuf,(unsigned char *)lptr,image->xsize);
1368 lptr += image->xsize;
1369 }
1370 else if(image->zsize == 3)
1371 {
1372 ImageGetRow(image,rbuf, y, 0);
1373 ImageGetRow(image,gbuf, y, 1);
1374 ImageGetRow(image,bbuf, y, 2);
1375 rgbtorgba(rbuf,gbuf,bbuf,(unsigned char *)lptr,image->xsize);
1376 lptr += image->xsize;
1377 }
1378 else if(image->zsize == 2)
1379 {
1380 ImageGetRow(image,rbuf, y, 0);
1381 ImageGetRow(image,abuf, y, 1);
1382 latorgba(rbuf,abuf,(unsigned char *)lptr,image->xsize);
1383 lptr += image->xsize;
1384 }
1385 else
1386 {
1387 ImageGetRow(image, rbuf, y, 0);
1388 bwtorgba(rbuf,(unsigned char *)lptr,image->xsize);
1389 lptr += image->xsize;
1390 }
1391 }
1392 ImageClose(image);
1393 free(rbuf);
1394 free(gbuf);
1395 free(bbuf);
1396 free(abuf);
1397
1398 return (unsigned *) base;
1399 }
1400
1401 /* Font texture conversion to mask texture */
1402 unsigned int *texture_to_mask(unsigned int *tex, int width, int height)
1403 {
1404 int nSize, i;
1405 unsigned int mask;
1406 unsigned *ret;
1407
1408 nSize = width * height;
1409 ret = (unsigned int *) malloc(nSize * sizeof(unsigned int));
1410
1411 // The literal is ordered internally according to the architecture, but tex
1412 // is an array of four color channels which may be in a different order.
1413 mask = LittleEndian() ? 0x00ffffff : mask = 0xffffff00;
1414
1415 for (i = 0; i < nSize; i++) {
1416 ret[i] = tex[i] & mask ? 0 : mask;
1417 }
1418
1419 return ret;
1420 }
1421
1422 /* Load BMF file format, function return bitmap font descriptor */
1423 int glfLoadBMFFont(const char *FName)
1424 {
1425 FILE *f;
1426 char Header[4];
1427 char FontName[97];
1428 int i, flag;
1429 int LEndian;
1430 float tx, ty, tw, th;
1431 unsigned char temp, *tp;
1432 unsigned *texture; /* Texture image */
1433 unsigned *mask; /* Mask texture */
1434 int twidth, theight, tcomp; /* Image parameters */
1435 float *temp_width;
1436
1437 LEndian = LittleEndian();
1438
1439 f = fopen(FName, "rb");
1440 if (f == NULL) return GLF_ERROR; /* Error opening file */
1441
1442 /* Get header */
1443 fread(Header, 1, 3, f);
1444 Header[3] = 0;
1445 if (strcmp(Header, "BMF")) return GLF_ERROR; /* Not BMF format */
1446
1447 /* Get font name */
1448 fread(FontName, 1, 96, f);
1449 FontName[96] = 0;
1450
1451 /* Allocate space for temp widths */
1452
1453 temp_width = (float *)malloc(sizeof(float)*256);
1454
1455 /* Read all 256 symbols information */
1456 for (i=0; i<256; i++) {
1457 fread(&tx, 4, 1, f);
1458 fread(&ty, 4, 1, f);
1459 fread(&tw, 4, 1, f);
1460 fread(&th, 4, 1, f);
1461
1462 if (!LEndian) {
1463 tp = (unsigned char *)&tx;
1464 temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
1465 temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
1466 tp = (unsigned char *)&ty;
1467 temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
1468 temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
1469 tp = (unsigned char *)&tw;
1470 temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
1471 temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
1472 tp = (unsigned char *)&th;
1473 temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
1474 temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
1475 }
1476
1477 Symbols[i].x = tx;
1478 Symbols[i].y = ty;
1479 Symbols[i].width = tw;
1480 Symbols[i].height = th;
1481 temp_width[i] = tw;
1482 }
1483
1484 /* Read texture image from file and build texture */
1485 texture = read_texture(f, &twidth, &theight, &tcomp);
1486 /* Generate mask texture */
1487 mask = texture_to_mask(texture, twidth, theight);
1488
1489 /* Find unused font descriptor */
1490 flag = 0;
1491 for (i=0; i<MAX_FONTS; i++)
1492 if (bmf_in_use[i] == 0)
1493 {
1494 /* Initialize this font */
1495 bmf_in_use[i] = 1;
1496 bmf_curfont = i;
1497 flag = 1;
1498 break;
1499 }
1500 if (!flag) /* Not enought space for new texture */
1501 {
1502 fclose(f);
1503 free(texture);
1504 free(mask);
1505 free(temp_width);
1506 return -1;
1507 }
1508
1509 m_widths[bmf_curfont].width = temp_width;
1510
1511 /* Generating textures for font and mask */
1512 glGenTextures(1, &bmf_texture[bmf_curfont]);
1513 glGenTextures(1, &bmf_mask[bmf_curfont]);
1514
1515 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1516
1517 /* Build font texture */
1518 glBindTexture(GL_TEXTURE_2D, bmf_texture[bmf_curfont]);
1519 glTexImage2D(GL_TEXTURE_2D, 0, 3, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
1520
1521 /* Linear filtering for better quality */
1522 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1523 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1524
1525 /* Build mask texture */
1526 glBindTexture(GL_TEXTURE_2D, bmf_mask[bmf_curfont]);
1527 glTexImage2D(GL_TEXTURE_2D, 0, 3, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, mask);
1528 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1529 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1530
1531 free(texture);
1532 free(mask);
1533 fclose(f);
1534
1535 /* Now build list for each symbol */
1536 list_base[bmf_curfont] = glGenLists(256);
1537 for (i=0; i<256; i++)
1538 {
1539 glNewList(list_base[bmf_curfont]+i, GL_COMPILE);
1540
1541 glBegin(GL_QUADS);
1542 glTexCoord2f(Symbols[i].x, Symbols[i].y); glVertex2f(0, 0);
1543 glTexCoord2f(Symbols[i].x+Symbols[i].width, Symbols[i].y); glVertex2f(Symbols[i].width, 0);
1544 glTexCoord2f(Symbols[i].x+Symbols[i].width, Symbols[i].y+Symbols[i].height); glVertex2f(Symbols[i].width, Symbols[i].height);
1545 glTexCoord2f(Symbols[i].x, Symbols[i].y+Symbols[i].height); glVertex2f(0, Symbols[i].height);
1546 glEnd();
1547 glTranslatef(Symbols[i].width+sym_space, 0, 0);
1548
1549 glEndList();
1550 if (Symbols[i].height > m_max_height[bmf_curfont]) m_max_height[bmf_curfont] = Symbols[i].height;
1551 }
1552 return bmf_curfont;
1553 }
1554 /* Unloads bitmap font by descriptor */
1555 int glfUnloadBMFFontD(int bmf_descriptor) {
1556 if ((bmf_descriptor < 0) || (bmf_in_use[bmf_descriptor] == 0)) return GLF_ERROR;
1557
1558 bmf_in_use[bmf_descriptor] = 0;
1559
1560 // glDeleteTextures(1, &bmf_texture[bmf_descriptor]);
1561 // glDeleteTextures(1, &bmf_mask[bmf_descriptor]);
1562 free(m_widths[bmf_descriptor].width);
1563
1564 if (bmf_descriptor == bmf_curfont) bmf_curfont = -1;
1565
1566 return GLF_OK;
1567 }
1568
1569 /* Unloads current bitmap font */
1570 int glfUnloadBMFFont() {
1571 return glfUnloadBMFFontD(bmf_curfont);
1572 }
1573
1574 /* Start bitmap drawing function */
1575 void glfStartBitmapDrawing() {
1576 /* Enable 2D Texturing */
1577 glGetBooleanv(GL_TEXTURE_2D, &bmf_texturing);
1578 glEnable(GL_TEXTURE_2D);
1579 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1580
1581 glBindTexture(GL_TEXTURE_2D, bmf_texture[bmf_curfont]);
1582 }
1583
1584 /* Stop bitmap drawing function */
1585 void glfStopBitmapDrawing()
1586 {
1587 /* Return previuos state of texturing */
1588 if (bmf_texturing) glEnable(GL_TEXTURE_2D);
1589 else glDisable(GL_TEXTURE_2D);
1590 }
1591
1592 /* Select current BMF font */
1593 int glfSetCurrentBMFFont(int Font_Descriptor)
1594 {
1595 if ((Font_Descriptor < 0) || (bmf_in_use[Font_Descriptor] == 0)) return GLF_ERROR;
1596
1597 bmf_curfont = Font_Descriptor;
1598 return GLF_OK;
1599 }
1600
1601 /* Get current BMF font */
1602 int glfGetCurrentBMFFont()
1603 {
1604 return bmf_curfont;
1605 }
1606
1607 /* Draw one bitmapped symbol by current font */
1608 void glfDrawBSymbol(char s)
1609 {
1610 if ((bmf_curfont < 0) || (bmf_in_use[bmf_curfont] == 0)) return;
1611
1612 glCallList(list_base[bmf_curfont]+(unsigned char)s);
1613 }
1614
1615 /* Draw bitmapped string */
1616 void glfDrawBString(const char *s)
1617 {
1618 GLfloat temp_trans;
1619 int i;
1620
1621 temp_trans = 0;
1622
1623 if ((bmf_curfont < 0) || (bmf_in_use[bmf_curfont] == 0)) return;
1624
1625 /* Calculate length of all string */
1626 for (i=0; i<(int)strlen(s); i++)
1627 temp_trans += m_widths[bmf_curfont].width[s[i]] + sym_space;
1628
1629 glListBase(list_base[bmf_curfont]);
1630 if (m_bitmap_string_center == GL_TRUE)
1631 {
1632 glPushMatrix();
1633 glTranslatef(-temp_trans/2, 0, 0);
1634 }
1635 glCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s);
1636 if (m_bitmap_string_center == GL_TRUE) glPopMatrix();
1637 }
1638
1639 void glfDrawBMaskSymbol(char s)
1640 {
1641 if ((bmf_curfont < 0) || (bmf_in_use[bmf_curfont] == 0)) return;
1642
1643 glPushMatrix();
1644 glPushAttrib(GL_CURRENT_BIT);
1645
1646 /* Draw the text as a mask in black */
1647 glColor3ub(0xff, 0xff, 0xff);
1648 glBlendFunc(GL_DST_COLOR, GL_ZERO);
1649 glBindTexture(GL_TEXTURE_2D, bmf_mask[bmf_curfont]);
1650
1651 glCallList(list_base[bmf_curfont]+(unsigned char)s);
1652
1653 glPopAttrib();
1654 glPopMatrix();
1655
1656 glBindTexture(GL_TEXTURE_2D, bmf_texture[bmf_curfont]);
1657
1658 /* Now draw the text over only the black bits in the requested color */
1659 glBlendFunc(GL_ONE, GL_ONE);
1660
1661 glCallList(list_base[bmf_curfont]+(unsigned char)s);
1662 }
1663
1664 void glfDrawBMaskString(const char *s)
1665 {
1666 GLfloat temp_trans;
1667 int i;
1668
1669 temp_trans = 0;
1670
1671 if ((bmf_curfont < 0) || (bmf_in_use[bmf_curfont] == 0)) return;
1672
1673 /* Calculate length of all string */
1674 for (i=0; i<(int)strlen(s); i++)
1675 temp_trans += m_widths[bmf_curfont].width[s[i]] + sym_space;
1676
1677 glDepthMask(GL_FALSE);
1678
1679 glPushMatrix();
1680 glPushAttrib(GL_CURRENT_BIT);
1681
1682 /* Draw the text as a mask in black */
1683 glColor3ub(0xff, 0xff, 0xff);
1684 glBlendFunc(GL_DST_COLOR, GL_ZERO);
1685 glBindTexture(GL_TEXTURE_2D, bmf_mask[bmf_curfont]);
1686
1687 glListBase(list_base[bmf_curfont]);
1688 if (m_bitmap_string_center == GL_TRUE)
1689 {
1690 glPushMatrix();
1691 glTranslatef(-temp_trans/2, 0, 0);
1692 }
1693 glCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s);
1694 if (m_bitmap_string_center == GL_TRUE) glPopMatrix();
1695
1696 glPopAttrib();
1697 glPopMatrix();
1698
1699 glBindTexture(GL_TEXTURE_2D, bmf_texture[bmf_curfont]);
1700
1701 /* Now draw the text over only the black bits in the requested color */
1702 glPushMatrix();
1703 glBlendFunc(GL_ONE, GL_ONE);
1704 glListBase(list_base[bmf_curfont]);
1705 if (m_bitmap_string_center == GL_TRUE) {
1706 glPushMatrix();
1707 glTranslatef(-temp_trans/2, 0, 0);
1708 }
1709 glCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s);
1710 if (m_bitmap_string_center == GL_TRUE) glPopMatrix();
1711 glPopMatrix();
1712
1713 glDepthMask(GL_TRUE);
1714 }
1715
1716 /* Set string centering for bitmap fonts */
1717 void glfBitmapStringCentering(GLboolean center)
1718 {
1719 m_bitmap_string_center = center;
1720 }
1721
1722 /* Set string centering for bitmap fonts */
1723 GLboolean glfBitmapGetStringCentering()
1724 {
1725 return m_bitmap_string_center;
1726 }
1727
1728 /* Set rotate angle for bitmap fonts */
1729 void glfSetBRotateAngle(float angle)
1730 {
1731 RotateAngleB = angle;
1732 }
1733