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