00001
00005 #include <math.h>
00006 #include <string.h>
00007 #include <stdio.h>
00008
00009 #include <allegro.h>
00010
00011 #include "alleggl.h"
00012 #include "allglint.h"
00013
00014 #ifdef ALLEGRO_MACOSX
00015 #include <OpenGL/glu.h>
00016 #else
00017 #include <GL/glu.h>
00018 #endif
00019
00020 #if defined ALLEGRO_WITH_XWINDOWS && !defined ALLEGROGL_GENERIC_DRIVER
00021 #include <xalleg.h>
00022 #include <GL/glx.h>
00023 #endif
00024
00025
00026
00027
00028 static int aglf_font_generation_mode = AGL_FONT_POLYGONS;
00029
00030
00031
00032
00033
00034 static AL_CONST FONT_AGL_DATA *find_range(AL_CONST FONT_AGL_DATA *f, int c) {
00035
00036 while (f) {
00037 if ((c >= f->start) && (c < f->end))
00038 return f;
00039
00040 f = f->next;
00041 }
00042
00043 return NULL;
00044 }
00045
00046
00047
00048
00049
00063 int allegro_gl_printf(AL_CONST FONT *f, float x, float y, float z, int color,
00064 AL_CONST char *format, ...) {
00065
00066 #define BUF_SIZE 1024
00067 char buf[BUF_SIZE];
00068 va_list ap;
00069
00070 if (!__allegro_gl_valid_context)
00071 return 0;
00072
00073
00074 va_start(ap, format);
00075 uvszprintf(buf, BUF_SIZE, format, ap);
00076 va_end(ap);
00077
00078 #undef BUF_SIZE
00079
00080
00081 {
00082 GLubyte c[4];
00083 c[0] = (GLubyte)getr(color);
00084 c[1] = (GLubyte)getg(color);
00085 c[2] = (GLubyte)getb(color);
00086 c[3] = (__allegro_gl_use_alpha && bitmap_color_depth(screen) == 32)
00087 ? (GLubyte)geta(color) : 255;
00088
00089 glColor4ubv(c);
00090 }
00091
00092 return allegro_gl_printf_ex(f, x, y, z, buf);
00093 }
00094
00095
00096
00097
00098
00099
00165 int allegro_gl_printf_ex(AL_CONST FONT *f, float x, float y, float z,
00166 AL_CONST char *format, ...) {
00167 #define BUF_SIZE 1024
00168 char buf[BUF_SIZE];
00169 va_list ap;
00170
00171 AL_CONST FONT_AGL_DATA *range = NULL;
00172 int c, pos = 0;
00173 int count = 0;
00174 AL_CONST FONT_AGL_DATA *d;
00175 GLint vert_order, cull_mode;
00176 GLint matrix_mode;
00177
00178 int restore_rasterpos = 0;
00179 GLuint old_texture_bind = 0;
00180 GLfloat old_raster_pos[4];
00181
00182
00183 if (!__allegro_gl_valid_context)
00184 return 0;
00185
00186
00187 if (!format || !f) {
00188 TRACE("** ERROR ** agl_printf: Null parameter\n");
00189 return 0;
00190 }
00191
00192 if (f->vtable != font_vtable_agl) {
00193 TRACE("** ERROR ** agl_printf: Font parameter isn't of the AGL "
00194 "type.\n");
00195 return 0;
00196 }
00197
00198 d = (AL_CONST FONT_AGL_DATA*)f->data;
00199
00200
00201 va_start(ap, format);
00202 uvszprintf(buf, BUF_SIZE, format, ap);
00203 va_end(ap);
00204
00205 #undef BUF_SIZE
00206
00207 allegro_gl_begin();
00208
00209 glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
00210 glGetIntegerv(GL_FRONT_FACE, &vert_order);
00211 glGetIntegerv(GL_CULL_FACE_MODE, &cull_mode);
00212
00213 glMatrixMode(GL_MODELVIEW_MATRIX);
00214 glPushMatrix();
00215
00216 glFrontFace(GL_CW);
00217 glCullFace(GL_BACK);
00218
00219 { GLint temp;
00220 glGetIntegerv(GL_TEXTURE_BINDING_2D, &temp);
00221 old_texture_bind = (GLuint)temp;
00222 }
00223
00224 if (d->type == AGL_FONT_TYPE_BITMAP) {
00225 glTranslatef(0, 0, -1);
00226 glBindTexture(GL_TEXTURE_2D, 0);
00227
00228 glGetFloatv(GL_CURRENT_RASTER_POSITION, old_raster_pos);
00229 glRasterPos2f(x, y);
00230 restore_rasterpos = 1;
00231 }
00232 else if (d->type == AGL_FONT_TYPE_OUTLINE) {
00233 glTranslatef(x, y, z);
00234 glBindTexture(GL_TEXTURE_2D, 0);
00235 }
00236 else if (d->type == AGL_FONT_TYPE_TEXTURED) {
00237 glTranslatef(x, y, z);
00238 }
00239
00240
00241 while ((c = ugetc(buf + pos)) != 0) {
00242
00243 pos += ucwidth(c);
00244
00245 if ((!range) || (c < range->start) || (c >= range->end)) {
00246
00247 range = find_range(d, c);
00248
00249 if (!range) {
00250 range = find_range(d, (c = '^'));
00251
00252 if (!range)
00253 continue;
00254 }
00255 }
00256
00257
00258 if (d->type == AGL_FONT_TYPE_TEXTURED) {
00259 glBindTexture(GL_TEXTURE_2D, range->texture);
00260 }
00261
00262
00263 c -= range->start;
00264 c += range->list_base;
00265
00266 glCallList(c);
00267
00268 count++;
00269 }
00270
00271 glPopMatrix();
00272
00273 glMatrixMode(matrix_mode);
00274 glFrontFace(vert_order);
00275 glCullFace(cull_mode);
00276
00277 glBindTexture(GL_TEXTURE_2D, old_texture_bind);
00278
00279 if (restore_rasterpos) {
00280 glRasterPos4fv(old_raster_pos);
00281 }
00282
00283 allegro_gl_end();
00284
00285 return count;
00286 }
00287
00288
00289
00290 #ifndef ALLEGROGL_GENERIC_DRIVER
00291 #ifdef ALLEGRO_WINDOWS
00292
00293 static FONT *win_load_system_font(char *name, int type, int style, int w, int h, float depth, int start, int end) {
00294
00295 HFONT hFont;
00296
00297 FONT_AGL_DATA *data;
00298 FONT *ret;
00299
00300 ret = malloc(sizeof(FONT));
00301 if (!ret) {
00302 TRACE("** ERROR ** win_load_system_font: Ran out of memory "
00303 "while allocating %i bytes\n", sizeof(FONT));
00304 return NULL;
00305 }
00306 data = malloc(sizeof(FONT_AGL_DATA));
00307 if (!data) {
00308 free(ret);
00309 TRACE("** ERROR ** win_load_system_font: Ran out of memory "
00310 "while allocating %i bytes\n", sizeof(FONT_AGL_DATA));
00311 return NULL;
00312 }
00313 ret->vtable = font_vtable_agl;
00314 ret->data = data;
00315
00316 data->list_base = glGenLists(end - start);
00317 data->start = start;
00318 data->end = end;
00319 data->next = NULL;
00320 data->is_free_chunk = 0;
00321
00322 if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
00323
00324 HDC dc;
00325
00326 hFont = CreateFont( -h, w,
00327 0, 0,
00328 (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
00329 : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
00330 ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
00331 ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
00332 ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
00333 ANSI_CHARSET,
00334 OUT_TT_PRECIS,
00335 CLIP_DEFAULT_PRECIS,
00336 (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
00337 : DEFAULT_QUALITY,
00338 FF_DONTCARE | DEFAULT_PITCH,
00339 name);
00340
00341 dc = GetDC(win_get_window());
00342
00343 SelectObject(dc, hFont);
00344
00345 wglUseFontBitmaps(dc, start, end - start, data->list_base);
00346 data->type = AGL_FONT_TYPE_BITMAP;
00347 data->data = NULL;
00348 }
00349 else if (type == AGL_FONT_TYPE_OUTLINE) {
00350 HDC dc;
00351
00352 GLYPHMETRICSFLOAT *gmf;
00353 gmf = malloc(sizeof(GLYPHMETRICSFLOAT) * (end - start));
00354 memset(gmf, 0, sizeof(GLYPHMETRICSFLOAT) * (end - start));
00355
00356 hFont = CreateFont( -h, w,
00357 0, 0,
00358 (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
00359 : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
00360 ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
00361 ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
00362 ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
00363 ANSI_CHARSET,
00364 OUT_TT_PRECIS,
00365 CLIP_DEFAULT_PRECIS,
00366 (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
00367 : DEFAULT_QUALITY,
00368 FF_DONTCARE | DEFAULT_PITCH,
00369 name);
00370
00371 dc = GetDC(win_get_window());
00372
00373 SelectObject(dc, hFont);
00374 wglUseFontOutlines(dc, start, end - start, data->list_base,
00375 0.0, depth, (aglf_font_generation_mode == AGL_FONT_POLYGONS)
00376 ? WGL_FONT_POLYGONS : WGL_FONT_LINES, gmf);
00377
00378 data->type = AGL_FONT_TYPE_OUTLINE;
00379 data->data = gmf;
00380 }
00381
00382 return ret;
00383 }
00384 #endif
00385
00386
00387
00388 #ifdef ALLEGRO_WITH_XWINDOWS
00389 static FONT *x_load_system_font(char *name, int type, int style, int w, int h,
00390 float depth, int start, int end) {
00391 FONT_AGL_DATA *data;
00392 FONT *ret;
00393 XFontStruct *xfont;
00394
00395 ret = malloc(sizeof(FONT));
00396 if (!ret) {
00397 TRACE("** ERROR ** x_load_system_font: Ran out of memory "
00398 "while allocating %i bytes\n", sizeof(FONT));
00399 return NULL;
00400 }
00401 data = malloc(sizeof(FONT_AGL_DATA));
00402 if (!data) {
00403 free(ret);
00404 TRACE("** ERROR ** x_load_system_font: Ran out of memory "
00405 "while allocating %i bytes\n", sizeof(FONT_AGL_DATA));
00406 return NULL;
00407 }
00408 ret->vtable = font_vtable_agl;
00409 ret->data = data;
00410
00411 data->list_base = glGenLists(end - start);
00412 data->start = start;
00413 data->end = end;
00414 data->next = NULL;
00415 data->is_free_chunk = 0;
00416
00417 if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
00418 char buf[256], major_type[256], minor_type[2];
00419
00420 usprintf(major_type, "medium");
00421 if (style & AGL_FONT_STYLE_BOLD)
00422 usprintf(major_type, "bold");
00423 minor_type[0] = (style & AGL_FONT_STYLE_ITALIC) ? 'i' : 'r';
00424 minor_type[1] = '\0';
00425
00426 usprintf(buf, "-*-%s-%s-%s-normal-*-%i-*-*-*-*-*-*-*", name,
00427 major_type, minor_type, h);
00428
00429 xfont = XLoadQueryFont(_xwin.display, buf);
00430 if (!xfont) {
00431 free(ret);
00432 free(data);
00433 TRACE("** ERROR ** x_load_system_font: Failed to load "
00434 "%s\n", buf);
00435 return NULL;
00436 }
00437 glXUseXFont(xfont->fid, start, end - start, data->list_base);
00438 data->type = AGL_FONT_TYPE_BITMAP;
00439 data->data = NULL;
00440 XFreeFont(_xwin.display, xfont);
00441 }
00442 else {
00443
00444 return NULL;
00445 }
00446
00447 return ret;
00448 }
00449 #endif
00450 #endif
00451
00452
00453
00454
00469 void allegro_gl_set_font_generation_mode(int mode) {
00470 aglf_font_generation_mode = mode;
00471 return;
00472 }
00473
00474
00475
00476
00485 FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) {
00486
00487 return allegro_gl_load_system_font_ex(name, AGL_FONT_TYPE_OUTLINE,
00488 style, w, h, 0.0f, 32, 256);
00489 }
00490
00491
00492
00493
00494
00526 FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
00527 int w, int h, float depth, int start, int end) {
00528
00529 FONT *ret = NULL;
00530
00531 if (!__allegro_gl_valid_context)
00532 return NULL;
00533
00534 if (!name) {
00535 TRACE("** ERROR ** load_system_font: Nameless font\n");
00536 return NULL;
00537 }
00538
00539
00540
00541 #ifndef ALLEGROGL_GENERIC_DRIVER
00542 #ifdef ALLEGRO_WINDOWS
00543 ret = win_load_system_font(name, type, style, w, h, depth, start, end);
00544 #elif defined ALLEGRO_UNIX
00545 ret = x_load_system_font(name, type, style, w, h, depth, start, end);
00546 #else
00547
00548 #endif
00549 #endif
00550
00551 return ret;
00552 }
00553
00554
00555
00571 void allegro_gl_destroy_font(FONT *f) {
00572
00573 FONT_AGL_DATA *data;
00574
00575 if (!f) {
00576 return;
00577 }
00578 if (f->vtable != font_vtable_agl) {
00579 TRACE("** ERROR ** destroy_font: Font is not of AGL type\n");
00580 return;
00581 }
00582
00583 data = f->data;
00584
00585 if (!data) {
00586 TRACE("** ERROR ** destroy_font: Font is inconsistent\n");
00587 return;
00588 }
00589
00590
00591 while (data) {
00592 FONT_AGL_DATA *datanext;
00593
00594
00595 if (data->type == AGL_FONT_TYPE_BITMAP
00596 || data->type == AGL_FONT_TYPE_OUTLINE
00597 || data->type == AGL_FONT_TYPE_TEXTURED) {
00598
00599 if (__allegro_gl_valid_context) {
00600 if (data->list_base)
00601 glDeleteLists(data->list_base, data->end - data->start);
00602 if (data->texture)
00603 glDeleteTextures(1, &data->texture);
00604 }
00605 }
00606 if (data->type == AGL_FONT_TYPE_OUTLINE) {
00607 if (data->data)
00608 free(data->data);
00609 }
00610 else if (data->type == AGL_FONT_TYPE_TEXTURED) {
00611 if (data->data)
00612 destroy_bitmap(data->data);
00613 if (data->glyph_coords)
00614 free(data->glyph_coords);
00615 }
00616 else if (data->type == AGL_FONT_TYPE_BITMAP) {
00617 if (data->data) {
00618 int i;
00619 FONT_GLYPH **gl = data->data;
00620 for (i = 0; i < data->end - data->start; i++) {
00621 if (gl[i])
00622 free(gl[i]);
00623 }
00624 free(gl);
00625 }
00626 }
00627 datanext = data->next;
00628
00629 if (data->is_free_chunk)
00630 free(data);
00631
00632 data = datanext;
00633 }
00634 free(f->data);
00635
00636 if (f != font)
00637 free(f);
00638
00639 return;
00640 }
00641
00642
00643
00644
00687 size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) {
00688
00689 size_t num_ids = 0;
00690 FONT_AGL_DATA *data;
00691
00692 if (!f) {
00693 return 0;
00694 }
00695 if (f->vtable != font_vtable_agl) {
00696 TRACE("** ERROR ** list_font_textures: Font is not of AGL type\n");
00697 return 0;
00698 }
00699
00700 data = f->data;
00701
00702 if (!data) {
00703 TRACE("** ERROR ** list_font_textures: Font is inconsistent\n");
00704 return 0;
00705 }
00706
00707 if (!__allegro_gl_valid_context) {
00708 return 0;
00709 }
00710
00711
00712 while (data) {
00713 if (data->texture) {
00714
00715
00716
00717 if (ids && num_ids < max_num_id) {
00718 ids[num_ids] = data->texture;
00719 }
00720 num_ids++;
00721 }
00722
00723 data = data->next;
00724 }
00725
00726 return num_ids;
00727 }
00728