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 FONT_AGL_DATA *find_range(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
00123 int allegro_gl_printf(FONT *f, float x, float y, float z, int color,
00124 char *format, ...) {
00125
00126 char buf[512];
00127 FONT_AGL_DATA *range = NULL;
00128 int c, pos = 0;
00129 int count = 0;
00130 va_list ap;
00131 FONT_AGL_DATA *d;
00132 GLint vert_order, cull_mode, blend_src, blend_dst;
00133 GLuint old_bind = 0;
00134
00135 if (!__allegro_gl_valid_context)
00136 return 0;
00137
00138
00139 if (!format || !f) {
00140 TRACE("** ERROR ** agl_printf: Null parameter\n");
00141 return 0;
00142 }
00143
00144 if (f->vtable != font_vtable_agl) {
00145 TRACE("** ERROR ** agl_printf: Font parameter isn't of the AGL "
00146 "type.\n");
00147 return 0;
00148 }
00149
00150 d = (FONT_AGL_DATA*)f->data;
00151
00152
00153 va_start(ap, format);
00154 uvsprintf(buf, format, ap);
00155 va_end(ap);
00156
00157
00158 allegro_gl_begin();
00159
00160
00161 {
00162 GLubyte c[4];
00163 c[0] = (GLubyte)getr(color);
00164 c[1] = (GLubyte)getg(color);
00165 c[2] = (GLubyte)getb(color);
00166 c[3] = (__allegro_gl_use_alpha && bitmap_color_depth(screen) == 32)
00167 ? (GLubyte)geta(color) : 255;
00168
00169 glColor4ubv(c);
00170 }
00171
00172 glPushMatrix();
00173
00174 glGetIntegerv(GL_FRONT_FACE, &vert_order);
00175 glGetIntegerv(GL_CULL_FACE_MODE, &cull_mode);
00176 glGetIntegerv(GL_BLEND_SRC, &blend_src);
00177 glGetIntegerv(GL_BLEND_DST, &blend_dst);
00178 glFrontFace(GL_CW);
00179 glCullFace(GL_BACK);
00180
00181 glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_bind);
00182
00183 if (d->type == AGL_FONT_TYPE_BITMAP) {
00184 glTranslatef(0, 0, -1);
00185
00186 glBlendFunc(GL_ONE, GL_ZERO);
00187 glBindTexture(GL_TEXTURE_2D, 0);
00188 glRasterPos2f(x, y);
00189 }
00190 else if (d->type == AGL_FONT_TYPE_OUTLINE) {
00191 glTranslatef(x, y, z);
00192 glBindTexture(GL_TEXTURE_2D, 0);
00193 }
00194 else if (d->type == AGL_FONT_TYPE_TEXTURED) {
00195 glTranslatef(x, y, z);
00196 }
00197
00198
00199 while ((c = ugetc(buf + pos)) != 0) {
00200
00201 pos += ucwidth(c);
00202
00203 if ((!range) || (c < range->start) || (c >= range->end)) {
00204
00205 range = find_range(d, c);
00206
00207 if (!range) {
00208 range = find_range(d, (c = '^'));
00209
00210 if (!range)
00211 continue;
00212 }
00213 }
00214
00215
00216 if (d->type == AGL_FONT_TYPE_TEXTURED) {
00217 glBindTexture(GL_TEXTURE_2D, range->texture);
00218 }
00219
00220
00221 c -= range->start;
00222 c += range->list_base;
00223
00224 glCallList(c);
00225
00226 count++;
00227 }
00228
00229 glPopMatrix();
00230
00231 glFrontFace(vert_order);
00232 glCullFace(cull_mode);
00233 glBlendFunc(blend_src, blend_dst);
00234
00235 glBindTexture(GL_TEXTURE_2D, old_bind);
00236
00237 allegro_gl_end();
00238
00239 return count;
00240 }
00241
00242
00243
00244 #ifndef ALLEGROGL_GENERIC_DRIVER
00245 #ifdef ALLEGRO_WINDOWS
00246
00247 static FONT *win_load_system_font(char *name, int type, int style, int w, int h, float depth, int start, int end) {
00248
00249 HFONT hFont;
00250
00251 FONT_AGL_DATA *data;
00252 FONT *ret;
00253
00254 ret = malloc(sizeof(FONT));
00255 if (!ret) {
00256 TRACE("** ERROR ** win_load_system_font: Ran out of memory "
00257 "while allocating %i bytes\n", sizeof(FONT));
00258 return NULL;
00259 }
00260 data = malloc(sizeof(FONT_AGL_DATA));
00261 if (!data) {
00262 free(ret);
00263 TRACE("** ERROR ** win_load_system_font: Ran out of memory "
00264 "while allocating %i bytes\n", sizeof(FONT_AGL_DATA));
00265 return NULL;
00266 }
00267 ret->vtable = font_vtable_agl;
00268 ret->data = data;
00269
00270 data->list_base = glGenLists(end - start);
00271 data->start = start;
00272 data->end = end;
00273 data->next = NULL;
00274 data->is_free_chunk = 0;
00275
00276 if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
00277
00278 HDC dc;
00279
00280 hFont = CreateFont( -h, w,
00281 0, 0,
00282 (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
00283 : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
00284 ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
00285 ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
00286 ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
00287 ANSI_CHARSET,
00288 OUT_TT_PRECIS,
00289 CLIP_DEFAULT_PRECIS,
00290 (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
00291 : DEFAULT_QUALITY,
00292 FF_DONTCARE | DEFAULT_PITCH,
00293 name);
00294
00295 dc = GetDC(win_get_window());
00296
00297 SelectObject(dc, hFont);
00298
00299 wglUseFontBitmaps(dc, start, end - start, data->list_base);
00300 data->type = AGL_FONT_TYPE_BITMAP;
00301 data->data = NULL;
00302 }
00303 else if (type == AGL_FONT_TYPE_OUTLINE) {
00304 HDC dc;
00305
00306 GLYPHMETRICSFLOAT *gmf;
00307 gmf = malloc(sizeof(GLYPHMETRICSFLOAT) * (end - start));
00308 memset(gmf, 0, sizeof(GLYPHMETRICSFLOAT) * (end - start));
00309
00310 hFont = CreateFont( -h, w,
00311 0, 0,
00312 (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
00313 : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
00314 ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
00315 ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
00316 ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
00317 ANSI_CHARSET,
00318 OUT_TT_PRECIS,
00319 CLIP_DEFAULT_PRECIS,
00320 (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
00321 : DEFAULT_QUALITY,
00322 FF_DONTCARE | DEFAULT_PITCH,
00323 name);
00324
00325 dc = GetDC(win_get_window());
00326
00327 SelectObject(dc, hFont);
00328 wglUseFontOutlines(dc, start, end - start, data->list_base,
00329 0.0, depth, (aglf_font_generation_mode == AGL_FONT_POLYGONS)
00330 ? WGL_FONT_POLYGONS : WGL_FONT_LINES, gmf);
00331
00332 data->type = AGL_FONT_TYPE_OUTLINE;
00333 data->data = gmf;
00334 }
00335
00336 return ret;
00337 }
00338 #endif
00339
00340
00341
00342 #ifdef ALLEGRO_WITH_XWINDOWS
00343 static FONT *x_load_system_font(char *name, int type, int style, int w, int h,
00344 float depth, int start, int end) {
00345 FONT_AGL_DATA *data;
00346 FONT *ret;
00347 XFontStruct *xfont;
00348
00349 ret = malloc(sizeof(FONT));
00350 if (!ret) {
00351 TRACE("** ERROR ** x_load_system_font: Ran out of memory "
00352 "while allocating %i bytes\n", sizeof(FONT));
00353 return NULL;
00354 }
00355 data = malloc(sizeof(FONT_AGL_DATA));
00356 if (!data) {
00357 free(ret);
00358 TRACE("** ERROR ** x_load_system_font: Ran out of memory "
00359 "while allocating %i bytes\n", sizeof(FONT_AGL_DATA));
00360 return NULL;
00361 }
00362 ret->vtable = font_vtable_agl;
00363 ret->data = data;
00364
00365 data->list_base = glGenLists(end - start);
00366 data->start = start;
00367 data->end = end;
00368 data->next = NULL;
00369 data->is_free_chunk = 0;
00370
00371 if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
00372 char buf[256], major_type[256], minor_type[2];
00373
00374 usprintf(major_type, "medium");
00375 if (style & AGL_FONT_STYLE_BOLD)
00376 usprintf(major_type, "bold");
00377 minor_type[0] = (style & AGL_FONT_STYLE_ITALIC) ? 'i' : 'r';
00378 minor_type[1] = '\0';
00379
00380 usprintf(buf, "-*-%s-%s-%s-normal-*-%i-*-*-*-*-*-*-*", name,
00381 major_type, minor_type, h);
00382
00383 xfont = XLoadQueryFont(_xwin.display, buf);
00384 if (!xfont) {
00385 free(ret);
00386 free(data);
00387 TRACE("** ERROR ** x_load_system_font: Failed to load "
00388 "%s\n", buf);
00389 return NULL;
00390 }
00391 glXUseXFont(xfont->fid, start, end - start, data->list_base);
00392 data->type = AGL_FONT_TYPE_BITMAP;
00393 data->data = NULL;
00394 XFreeFont(_xwin.display, xfont);
00395 }
00396 else {
00397
00398 return NULL;
00399 }
00400
00401 return ret;
00402 }
00403 #endif
00404 #endif
00405
00406
00407
00408
00423 void allegro_gl_set_font_generation_mode(int mode) {
00424 aglf_font_generation_mode = mode;
00425 return;
00426 }
00427
00428
00429
00430
00439 FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) {
00440
00441 return allegro_gl_load_system_font_ex(name, AGL_FONT_TYPE_OUTLINE,
00442 style, w, h, 0.0f, 32, 256);
00443 }
00444
00445
00446
00447
00448
00480 FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
00481 int w, int h, float depth, int start, int end) {
00482
00483 FONT *ret = NULL;
00484
00485 if (!__allegro_gl_valid_context)
00486 return NULL;
00487
00488 if (!name) {
00489 TRACE("** ERROR ** load_system_font: Nameless font\n");
00490 return NULL;
00491 }
00492
00493
00494
00495 #ifndef ALLEGROGL_GENERIC_DRIVER
00496 #ifdef ALLEGRO_WINDOWS
00497 ret = win_load_system_font(name, type, style, w, h, depth, start, end);
00498 #elif defined ALLEGRO_UNIX
00499 ret = x_load_system_font(name, type, style, w, h, depth, start, end);
00500 #else
00501
00502 #endif
00503 #endif
00504
00505 return ret;
00506 }
00507
00508
00509
00525 void allegro_gl_destroy_font(FONT *f) {
00526
00527 FONT_AGL_DATA *data;
00528
00529 if (!f) {
00530 return;
00531 }
00532 if (f->vtable != font_vtable_agl) {
00533 TRACE("** ERROR ** destroy_font: Font is not of AGL type\n");
00534 return;
00535 }
00536
00537 data = f->data;
00538
00539 if (!data) {
00540 TRACE("** ERROR ** destroy_font: Font is inconsistent\n");
00541 return;
00542 }
00543
00544
00545 while (data) {
00546 FONT_AGL_DATA *datanext;
00547
00548
00549 if (data->type == AGL_FONT_TYPE_BITMAP
00550 || data->type == AGL_FONT_TYPE_OUTLINE
00551 || data->type == AGL_FONT_TYPE_TEXTURED) {
00552
00553 if (__allegro_gl_valid_context) {
00554 if (data->list_base)
00555 glDeleteLists(data->list_base, data->end - data->start);
00556 if (data->texture)
00557 glDeleteTextures(1, &data->texture);
00558 }
00559 }
00560 if (data->type == AGL_FONT_TYPE_OUTLINE) {
00561 if (data->data)
00562 free(data->data);
00563 }
00564 else if (data->type == AGL_FONT_TYPE_TEXTURED) {
00565 if (data->data)
00566 destroy_bitmap(data->data);
00567 }
00568 else if (data->type == AGL_FONT_TYPE_BITMAP) {
00569 if (data->data) {
00570 int i;
00571 FONT_GLYPH **gl = data->data;
00572 for (i = 0; i < data->end - data->start; i++) {
00573 if (gl[i])
00574 free(gl[i]);
00575 }
00576 free(gl);
00577 }
00578 }
00579 datanext = data->next;
00580
00581 if (data->is_free_chunk)
00582 free(data);
00583
00584 data = datanext;
00585 }
00586 free(f->data);
00587
00588 if (f != font)
00589 free(f);
00590
00591 return;
00592 }
00593
00594
00595
00596
00639 size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) {
00640
00641 size_t num_ids = 0;
00642 FONT_AGL_DATA *data;
00643
00644 if (!f) {
00645 return 0;
00646 }
00647 if (f->vtable != font_vtable_agl) {
00648 TRACE("** ERROR ** list_font_textures: Font is not of AGL type\n");
00649 return 0;
00650 }
00651
00652 data = f->data;
00653
00654 if (!data) {
00655 TRACE("** ERROR ** list_font_textures: Font is inconsistent\n");
00656 return 0;
00657 }
00658
00659 if (!__allegro_gl_valid_context) {
00660 return 0;
00661 }
00662
00663
00664 while (data) {
00665 if (data->texture) {
00666
00667
00668
00669 if (ids && num_ids < max_num_id) {
00670 ids[num_ids] = data->texture;
00671 }
00672 num_ids++;
00673 }
00674
00675 data = data->next;
00676 }
00677
00678 return num_ids;
00679 }
00680