AllegroGL  0.4.4
aglf.c
Go to the documentation of this file.
1 /* This code is (C) AllegroGL contributors, and double licensed under
2  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
3  */
8 #include <math.h>
9 #include <string.h>
10 #include <stdio.h>
11 
12 #include "allegro.h"
13 
14 #include "alleggl.h"
15 #include "allglint.h"
16 
17 #ifdef ALLEGRO_MACOSX
18 #include <OpenGL/glu.h>
19 #else
20 #include <GL/glu.h>
21 #endif
22 
23 #if defined ALLEGRO_WITH_XWINDOWS && !defined ALLEGROGL_GENERIC_DRIVER
24 #include <xalleg.h>
25 #include <GL/glx.h>
26 #endif
27 
28 #define PREFIX_E "agl-font ERROR: "
29 
30 
31 
32 static int aglf_font_generation_mode = AGL_FONT_POLYGONS;
33 
34 
35 /* find_range:
36  * Searches a font for a specific character.
37  */
38 static AL_CONST FONT_AGL_DATA *find_range(AL_CONST FONT_AGL_DATA *f, int c) {
39 
40  while (f) {
41  if ((c >= f->start) && (c < f->end))
42  return f;
43 
44  f = f->next;
45  }
46 
47  return NULL;
48 }
49 
50 
51 
52 /* allegro_gl_printf(FONT *f, float x, float y, float z, int color,
53  char *format, ...) */
67 int allegro_gl_printf(AL_CONST FONT *f, float x, float y, float z, int color,
68  AL_CONST char *format, ...) {
69 
70 #define BUF_SIZE 1024
71  char buf[BUF_SIZE];
72  va_list ap;
73 
74  if (!__allegro_gl_valid_context)
75  return 0;
76 
77  /* Get the string */
78  va_start(ap, format);
79  uvszprintf(buf, BUF_SIZE, format, ap);
80  va_end(ap);
81 
82 #undef BUF_SIZE
83 
84  /* Set color */
85  {
86  GLubyte c[4];
87  c[0] = (GLubyte)getr(color);
88  c[1] = (GLubyte)getg(color);
89  c[2] = (GLubyte)getb(color);
90  c[3] = (__allegro_gl_use_alpha && bitmap_color_depth(screen) == 32)
91  ? (GLubyte)geta(color) : 255;
92 
93  glColor4ubv(c);
94  }
95 
96  return allegro_gl_printf_ex(f, x, y, z, buf);
97 }
98 
99 
100 
101 /* allegro_gl_printf_ex(FONT *f, float x, float y, float z,
102  * char *format, ...)
103  */
169 int allegro_gl_printf_ex(AL_CONST FONT *f, float x, float y, float z,
170  AL_CONST char *format, ...) {
171  #define BUF_SIZE 1024
172  char buf[BUF_SIZE];
173  va_list ap;
174 
175  AL_CONST FONT_AGL_DATA *range = NULL;
176  int c, pos = 0;
177  int count = 0;
178  AL_CONST FONT_AGL_DATA *d;
179  GLint vert_order, cull_mode;
180  GLint matrix_mode;
181 
182  int restore_rasterpos = 0;
183  GLuint old_texture_bind = 0;
184  GLfloat old_raster_pos[4];
185 
186 
187  if (!__allegro_gl_valid_context)
188  return 0;
189 
190  /* Check arguments */
191  if (!format || !f) {
192  TRACE(PREFIX_E "agl_printf: Null parameter\n");
193  return 0;
194  }
195 
196  if (f->vtable != font_vtable_agl) {
197  TRACE(PREFIX_E "agl_printf: Font parameter isn't of the AGL "
198  "type.\n");
199  return 0;
200  }
201 
202  d = (AL_CONST FONT_AGL_DATA*)f->data;
203 
204  /* Get the string */
205  va_start(ap, format);
206  uvszprintf(buf, BUF_SIZE, format, ap);
207  va_end(ap);
208 
209 #undef BUF_SIZE
210 
211  glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
212  glGetIntegerv(GL_FRONT_FACE, &vert_order);
213  glGetIntegerv(GL_CULL_FACE_MODE, &cull_mode);
214 
215  glMatrixMode(GL_MODELVIEW);
216  glPushMatrix();
217 
218  glFrontFace(GL_CW);
219  glCullFace(GL_BACK);
220 
221  { GLint temp;
222  glGetIntegerv(GL_TEXTURE_BINDING_2D, &temp);
223  old_texture_bind = (GLuint)temp;
224  }
225 
226  if (d->type == AGL_FONT_TYPE_BITMAP) {
227  glTranslatef(0, 0, -1);
228  glBindTexture(GL_TEXTURE_2D, 0);
229 
230  glGetFloatv(GL_CURRENT_RASTER_POSITION, old_raster_pos);
231  glRasterPos2f(x, y);
232  restore_rasterpos = 1;
233  }
234  else if (d->type == AGL_FONT_TYPE_OUTLINE) {
235  glTranslatef(x, y, z);
236  glBindTexture(GL_TEXTURE_2D, 0);
237  }
238  else if (d->type == AGL_FONT_TYPE_TEXTURED) {
239  glTranslatef(x, y, z);
240  }
241 
242 
243  while ((c = ugetc(buf + pos)) != 0) {
244 
245  pos += ucwidth(c);
246 
247  if ((!range) || (c < range->start) || (c >= range->end)) {
248  /* search for a suitable character range */
249  range = find_range(d, c);
250 
251  if (!range) {
252  range = find_range(d, (c = '^'));
253 
254  if (!range)
255  continue;
256  }
257  }
258 
259  /* Set up texture */
260  if (d->type == AGL_FONT_TYPE_TEXTURED) {
261  glBindTexture(GL_TEXTURE_2D, range->texture);
262  }
263 
264  /* draw the character */
265  c -= range->start;
266  c += range->list_base;
267 
268  glCallList(c);
269 
270  count++;
271  }
272 
273  glPopMatrix();
274 
275  glMatrixMode(matrix_mode);
276  glFrontFace(vert_order);
277  glCullFace(cull_mode);
278 
279  glBindTexture(GL_TEXTURE_2D, old_texture_bind);
280 
281  if (restore_rasterpos) {
282  glRasterPos4fv(old_raster_pos);
283  }
284 
285  return count;
286 }
287 
288 
289 
290 #ifndef ALLEGROGL_GENERIC_DRIVER
291 #ifdef ALLEGRO_WINDOWS
292 
293 static FONT *win_load_system_font(char *name, int type, int style, int w, int h, float depth, int start, int end) {
294 
295  HFONT hFont;
296 
297  FONT_AGL_DATA *data;
298  FONT *ret;
299 
300  ret = malloc(sizeof(FONT));
301  if (!ret) {
302  TRACE(PREFIX_E "win_load_system_font: Ran out of memory "
303  "while allocating %i bytes\n", sizeof(FONT));
304  return NULL;
305  }
306  data = malloc(sizeof(FONT_AGL_DATA));
307  if (!data) {
308  free(ret);
309  TRACE(PREFIX_E "win_load_system_font: Ran out of memory "
310  "while allocating %i bytes\n", sizeof(FONT_AGL_DATA));
311  return NULL;
312  }
313  ret->vtable = font_vtable_agl;
314  ret->data = data;
315 
316  data->list_base = glGenLists(end - start);
317  data->start = start;
318  data->end = end;
319  data->next = NULL;
320  data->is_free_chunk = 0;
321 
322  if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
323 
324  HDC dc;
325 
326  hFont = CreateFont( -h, w,
327  0, 0,
328  (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
329  : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
330  ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
331  ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
332  ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
333  ANSI_CHARSET,
334  OUT_TT_PRECIS,
335  CLIP_DEFAULT_PRECIS,
336  (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
337  : DEFAULT_QUALITY,
338  FF_DONTCARE | DEFAULT_PITCH,
339  name);
340 
341  dc = GetDC(win_get_window());
342 
343  SelectObject(dc, hFont);
344 
345  wglUseFontBitmaps(dc, start, end - start, data->list_base);
346  data->type = AGL_FONT_TYPE_BITMAP;
347  data->data = NULL;
348  }
349  else if (type == AGL_FONT_TYPE_OUTLINE) {
350  HDC dc;
351 
352  GLYPHMETRICSFLOAT *gmf;
353  gmf = malloc(sizeof(GLYPHMETRICSFLOAT) * (end - start));
354  memset(gmf, 0, sizeof(GLYPHMETRICSFLOAT) * (end - start));
355 
356  hFont = CreateFont( -h, w,
357  0, 0,
358  (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
359  : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
360  ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
361  ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
362  ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
363  ANSI_CHARSET,
364  OUT_TT_PRECIS,
365  CLIP_DEFAULT_PRECIS,
366  (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
367  : DEFAULT_QUALITY,
368  FF_DONTCARE | DEFAULT_PITCH,
369  name);
370 
371  dc = GetDC(win_get_window());
372 
373  SelectObject(dc, hFont);
374  wglUseFontOutlines(dc, start, end - start, data->list_base,
375  0.0, depth, (aglf_font_generation_mode == AGL_FONT_POLYGONS)
376  ? WGL_FONT_POLYGONS : WGL_FONT_LINES, gmf);
377 
378  data->type = AGL_FONT_TYPE_OUTLINE;
379  data->data = gmf;
380  }
381 
382  return ret;
383 }
384 #endif
385 
386 
387 
388 #ifdef ALLEGRO_WITH_XWINDOWS
389 static FONT *x_load_system_font(char *name, int type, int style, int w, int h,
390  float depth, int start, int end) {
391  FONT_AGL_DATA *data;
392  FONT *ret;
393  XFontStruct *xfont;
394 
395  ret = malloc(sizeof(FONT));
396  if (!ret) {
397  TRACE(PREFIX_E "x_load_system_font: Ran out of memory "
398  "while allocating %zi bytes\n", sizeof(FONT));
399  return NULL;
400  }
401  data = malloc(sizeof(FONT_AGL_DATA));
402  if (!data) {
403  free(ret);
404  TRACE(PREFIX_E "x_load_system_font: Ran out of memory "
405  "while allocating %zi bytes\n", sizeof(FONT_AGL_DATA));
406  return NULL;
407  }
408  ret->vtable = font_vtable_agl;
409  ret->data = data;
410 
411  data->list_base = glGenLists(end - start);
412  data->start = start;
413  data->end = end;
414  data->next = NULL;
415  data->is_free_chunk = 0;
416 
417  if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
418  char buf[256], major_type[256], minor_type[2];
419 
420  usprintf(major_type, "medium");
421  if (style & AGL_FONT_STYLE_BOLD)
422  usprintf(major_type, "bold");
423  minor_type[0] = (style & AGL_FONT_STYLE_ITALIC) ? 'i' : 'r';
424  minor_type[1] = '\0';
425 
426  usprintf(buf, "-*-%s-%s-%s-normal-*-%i-*-*-*-*-*-*-*", name,
427  major_type, minor_type, h);
428  /* Load the font */
429  xfont = XLoadQueryFont(_xwin.display, buf);
430  if (!xfont) {
431  free(ret);
432  free(data);
433  TRACE(PREFIX_E "x_load_system_font: Failed to load "
434  "%s\n", buf);
435  return NULL;
436  }
437  glXUseXFont(xfont->fid, start, end - start, data->list_base);
438  data->type = AGL_FONT_TYPE_BITMAP;
439  data->data = NULL;
440  XFreeFont(_xwin.display, xfont);
441  }
442  else {
443  /* Not Yet Implemented */
444  return NULL;
445  }
446 
447  return ret;
448 }
449 #endif
450 #endif /* ALLEGROGL_GENERIC_DRIVER */
451 
452 
453 
454 /* void allegro_gl_set_font_generation_mode(int mode) */
470  aglf_font_generation_mode = mode;
471  return;
472 }
473 
474 
475 
476 /* FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) */
485 FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) {
486 
488  style, w, h, 0.0f, 32, 256);
489 }
490 
491 
492 
493 /* FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
494  int w, int h, float depth, int start, int end) */
526 FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
527  int w, int h, float depth, int start, int end) {
528 
529  FONT *ret = NULL;
530 
531  if (!__allegro_gl_valid_context)
532  return NULL;
533 
534  if (!name) {
535  TRACE(PREFIX_E "load_system_font: Nameless font\n");
536  return NULL;
537  }
538 
539  /* Load a system font */
540 
541 #ifndef ALLEGROGL_GENERIC_DRIVER
542 #ifdef ALLEGRO_WINDOWS
543  ret = win_load_system_font(name, type, style, w, h, depth, start, end);
544 #elif defined ALLEGRO_UNIX
545  XLOCK();
546  ret = x_load_system_font(name, type, style, w, h, depth, start, end);
547  XUNLOCK();
548 #else
549  /* Other platform */
550 #endif
551 #endif
552 
553  return ret;
554 }
555 
556 
557 
573 void allegro_gl_destroy_font(FONT *f) {
574 
575  FONT_AGL_DATA *data;
576 
577  if (!f) {
578  return;
579  }
580  if (f->vtable != font_vtable_agl) {
581  TRACE(PREFIX_E "destroy_font: Font is not of AGL type\n");
582  return;
583  }
584 
585  data = f->data;
586 
587  if (!data) {
588  TRACE(PREFIX_E "destroy_font: Font is inconsistent\n");
589  return;
590  }
591 
592  /* Iterate through every segment of the font */
593  while (data) {
594  FONT_AGL_DATA *datanext;
595 
596  /* Release all resources taken up by this font */
597  if (data->type == AGL_FONT_TYPE_BITMAP
598  || data->type == AGL_FONT_TYPE_OUTLINE
599  || data->type == AGL_FONT_TYPE_TEXTURED) {
600 
601  if (__allegro_gl_valid_context) {
602  if (data->list_base)
603  glDeleteLists(data->list_base, data->end - data->start);
604  if (data->texture)
605  glDeleteTextures(1, &data->texture);
606  }
607  }
608  if (data->type == AGL_FONT_TYPE_OUTLINE) {
609  if (data->data)
610  free(data->data);
611  }
612  else if (data->type == AGL_FONT_TYPE_TEXTURED) {
613  if (data->data)
614  destroy_bitmap(data->data);
615  if (data->glyph_coords)
616  free(data->glyph_coords);
617  }
618  else if (data->type == AGL_FONT_TYPE_BITMAP) {
619  if (data->data) {
620  int i;
621  FONT_GLYPH **gl = data->data;
622  for (i = 0; i < data->end - data->start; i++) {
623  if (gl[i])
624  free(gl[i]);
625  }
626  free(gl);
627  }
628  }
629  datanext = data->next;
630 
631  if (data->is_free_chunk)
632  free(data);
633 
634  data = datanext;
635  }
636  free(f->data);
637 
638  if (f != font)
639  free(f);
640 
641  return;
642 }
643 
644 
645 
646 /* size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) */
689 size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) {
690 
691  size_t num_ids = 0;
692  FONT_AGL_DATA *data;
693 
694  if (!f) {
695  return 0;
696  }
697  if (f->vtable != font_vtable_agl) {
698  TRACE(PREFIX_E "list_font_textures: Font is not of AGL type\n");
699  return 0;
700  }
701 
702  data = f->data;
703 
704  if (!data) {
705  TRACE(PREFIX_E "list_font_textures: Font is inconsistent\n");
706  return 0;
707  }
708 
709  if (!__allegro_gl_valid_context) {
710  return 0;
711  }
712 
713  /* Iterate through all font segments */
714  while (data) {
715  if (data->texture) {
716  /* Add the texture ID in the array, if it's not NULL and if there
717  * is room.
718  */
719  if (ids && num_ids < max_num_id) {
720  ids[num_ids] = data->texture;
721  }
722  num_ids++;
723  }
724 
725  data = data->next;
726  }
727 
728  return num_ids;
729 }
730 
#define AGL_FONT_STYLE_STRIKEOUT
Creates a font with striked out characters.
Definition: alleggl.h:684
int allegro_gl_printf_ex(AL_CONST FONT *f, float x, float y, float z, AL_CONST char *format,...)
Prints a formatted string (printf style) on the screen.
Definition: aglf.c:169
#define AGL_FONT_STYLE_BOLD
Creates a font with bold characters.
Definition: alleggl.h:664
void allegro_gl_set_font_generation_mode(int mode)
Set the font generation mode for system fonts.
Definition: aglf.c:469
FONT * allegro_gl_load_system_font_ex(char *name, int type, int style, int w, int h, float depth, int start, int end)
Loads a system font.
Definition: aglf.c:526
void allegro_gl_destroy_font(FONT *f)
void allegro_gl_destroy_font(FONT *usefont)
Definition: aglf.c:573
#define AGL_FONT_STYLE_UNDERLINE
Creates a font with underlined characters.
Definition: alleggl.h:679
size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id)
List the texture ID of all textures forming the specified font.
Definition: aglf.c:689
#define AGL_FONT_TYPE_TEXTURED
Indicates that you want fonts to be converted to a texture format.
Definition: alleggl.h:656
FONT * allegro_gl_load_system_font(char *name, int style, int w, int h)
Short hand for aglf_load_system_font_ex(name, AGL_FONT_TYPE_OUTLINE, style, w, h, 0...
Definition: aglf.c:485
#define AGL_FONT_STYLE_BLACK
Creates a font with black (strong bold) characters.
Definition: alleggl.h:669
#define AGL_FONT_STYLE_ANTI_ALIASED
Creates a font with anti-aliased characters.
Definition: alleggl.h:691
#define AGL_FONT_STYLE_ITALIC
Creates a font with italicized characters.
Definition: alleggl.h:674
#define AGL_FONT_TYPE_BITMAP
Indicates that you want fonts to be converted to a bitmap format.
Definition: alleggl.h:632
#define AGL_FONT_TYPE_OUTLINE
Indicates that you want fonts to be converted to an outline format.
Definition: alleggl.h:644
Main header file for AllegroGL.
#define AGL_FONT_TYPE_DONT_CARE
Indicates that you don&#39;t really care how a font will be converted.
Definition: alleggl.h:621
#define AGL_FONT_POLYGONS
Font generation mode.
Definition: alleggl.h:699
int allegro_gl_printf(AL_CONST FONT *f, float x, float y, float z, int color, AL_CONST char *format,...)
Equivalent to:
Definition: aglf.c:67