AllegroGL 0.4.4
|
00001 /* This code is (C) AllegroGL contributors, and double licensed under 00002 * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. 00003 */ 00008 #include <math.h> 00009 #include <string.h> 00010 #include <stdio.h> 00011 00012 #include "allegro.h" 00013 00014 #include "alleggl.h" 00015 #include "allglint.h" 00016 00017 #ifdef ALLEGRO_MACOSX 00018 #include <OpenGL/glu.h> 00019 #else 00020 #include <GL/glu.h> 00021 #endif 00022 00023 #if defined ALLEGRO_WITH_XWINDOWS && !defined ALLEGROGL_GENERIC_DRIVER 00024 #include <xalleg.h> 00025 #include <GL/glx.h> 00026 #endif 00027 00028 #define PREFIX_E "agl-font ERROR: " 00029 00030 00031 00032 static int aglf_font_generation_mode = AGL_FONT_POLYGONS; 00033 00034 00035 /* find_range: 00036 * Searches a font for a specific character. 00037 */ 00038 static AL_CONST FONT_AGL_DATA *find_range(AL_CONST FONT_AGL_DATA *f, int c) { 00039 00040 while (f) { 00041 if ((c >= f->start) && (c < f->end)) 00042 return f; 00043 00044 f = f->next; 00045 } 00046 00047 return NULL; 00048 } 00049 00050 00051 00052 /* allegro_gl_printf(FONT *f, float x, float y, float z, int color, 00053 char *format, ...) */ 00067 int allegro_gl_printf(AL_CONST FONT *f, float x, float y, float z, int color, 00068 AL_CONST char *format, ...) { 00069 00070 #define BUF_SIZE 1024 00071 char buf[BUF_SIZE]; 00072 va_list ap; 00073 00074 if (!__allegro_gl_valid_context) 00075 return 0; 00076 00077 /* Get the string */ 00078 va_start(ap, format); 00079 uvszprintf(buf, BUF_SIZE, format, ap); 00080 va_end(ap); 00081 00082 #undef BUF_SIZE 00083 00084 /* Set color */ 00085 { 00086 GLubyte c[4]; 00087 c[0] = (GLubyte)getr(color); 00088 c[1] = (GLubyte)getg(color); 00089 c[2] = (GLubyte)getb(color); 00090 c[3] = (__allegro_gl_use_alpha && bitmap_color_depth(screen) == 32) 00091 ? (GLubyte)geta(color) : 255; 00092 00093 glColor4ubv(c); 00094 } 00095 00096 return allegro_gl_printf_ex(f, x, y, z, buf); 00097 } 00098 00099 00100 00101 /* allegro_gl_printf_ex(FONT *f, float x, float y, float z, 00102 * char *format, ...) 00103 */ 00169 int allegro_gl_printf_ex(AL_CONST FONT *f, float x, float y, float z, 00170 AL_CONST char *format, ...) { 00171 #define BUF_SIZE 1024 00172 char buf[BUF_SIZE]; 00173 va_list ap; 00174 00175 AL_CONST FONT_AGL_DATA *range = NULL; 00176 int c, pos = 0; 00177 int count = 0; 00178 AL_CONST FONT_AGL_DATA *d; 00179 GLint vert_order, cull_mode; 00180 GLint matrix_mode; 00181 00182 int restore_rasterpos = 0; 00183 GLuint old_texture_bind = 0; 00184 GLfloat old_raster_pos[4]; 00185 00186 00187 if (!__allegro_gl_valid_context) 00188 return 0; 00189 00190 /* Check arguments */ 00191 if (!format || !f) { 00192 TRACE(PREFIX_E "agl_printf: Null parameter\n"); 00193 return 0; 00194 } 00195 00196 if (f->vtable != font_vtable_agl) { 00197 TRACE(PREFIX_E "agl_printf: Font parameter isn't of the AGL " 00198 "type.\n"); 00199 return 0; 00200 } 00201 00202 d = (AL_CONST FONT_AGL_DATA*)f->data; 00203 00204 /* Get the string */ 00205 va_start(ap, format); 00206 uvszprintf(buf, BUF_SIZE, format, ap); 00207 va_end(ap); 00208 00209 #undef BUF_SIZE 00210 00211 glGetIntegerv(GL_MATRIX_MODE, &matrix_mode); 00212 glGetIntegerv(GL_FRONT_FACE, &vert_order); 00213 glGetIntegerv(GL_CULL_FACE_MODE, &cull_mode); 00214 00215 glMatrixMode(GL_MODELVIEW); 00216 glPushMatrix(); 00217 00218 glFrontFace(GL_CW); 00219 glCullFace(GL_BACK); 00220 00221 { GLint temp; 00222 glGetIntegerv(GL_TEXTURE_BINDING_2D, &temp); 00223 old_texture_bind = (GLuint)temp; 00224 } 00225 00226 if (d->type == AGL_FONT_TYPE_BITMAP) { 00227 glTranslatef(0, 0, -1); 00228 glBindTexture(GL_TEXTURE_2D, 0); 00229 00230 glGetFloatv(GL_CURRENT_RASTER_POSITION, old_raster_pos); 00231 glRasterPos2f(x, y); 00232 restore_rasterpos = 1; 00233 } 00234 else if (d->type == AGL_FONT_TYPE_OUTLINE) { 00235 glTranslatef(x, y, z); 00236 glBindTexture(GL_TEXTURE_2D, 0); 00237 } 00238 else if (d->type == AGL_FONT_TYPE_TEXTURED) { 00239 glTranslatef(x, y, z); 00240 } 00241 00242 00243 while ((c = ugetc(buf + pos)) != 0) { 00244 00245 pos += ucwidth(c); 00246 00247 if ((!range) || (c < range->start) || (c >= range->end)) { 00248 /* search for a suitable character range */ 00249 range = find_range(d, c); 00250 00251 if (!range) { 00252 range = find_range(d, (c = '^')); 00253 00254 if (!range) 00255 continue; 00256 } 00257 } 00258 00259 /* Set up texture */ 00260 if (d->type == AGL_FONT_TYPE_TEXTURED) { 00261 glBindTexture(GL_TEXTURE_2D, range->texture); 00262 } 00263 00264 /* draw the character */ 00265 c -= range->start; 00266 c += range->list_base; 00267 00268 glCallList(c); 00269 00270 count++; 00271 } 00272 00273 glPopMatrix(); 00274 00275 glMatrixMode(matrix_mode); 00276 glFrontFace(vert_order); 00277 glCullFace(cull_mode); 00278 00279 glBindTexture(GL_TEXTURE_2D, old_texture_bind); 00280 00281 if (restore_rasterpos) { 00282 glRasterPos4fv(old_raster_pos); 00283 } 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(PREFIX_E "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(PREFIX_E "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(PREFIX_E "x_load_system_font: Ran out of memory " 00398 "while allocating %zi bytes\n", sizeof(FONT)); 00399 return NULL; 00400 } 00401 data = malloc(sizeof(FONT_AGL_DATA)); 00402 if (!data) { 00403 free(ret); 00404 TRACE(PREFIX_E "x_load_system_font: Ran out of memory " 00405 "while allocating %zi 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 /* Load the font */ 00429 xfont = XLoadQueryFont(_xwin.display, buf); 00430 if (!xfont) { 00431 free(ret); 00432 free(data); 00433 TRACE(PREFIX_E "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 /* Not Yet Implemented */ 00444 return NULL; 00445 } 00446 00447 return ret; 00448 } 00449 #endif 00450 #endif /* ALLEGROGL_GENERIC_DRIVER */ 00451 00452 00453 00454 /* void allegro_gl_set_font_generation_mode(int mode) */ 00469 void allegro_gl_set_font_generation_mode(int mode) { 00470 aglf_font_generation_mode = mode; 00471 return; 00472 } 00473 00474 00475 00476 /* FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) */ 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 /* FONT *allegro_gl_load_system_font_ex(char *name, int type, int style, 00494 int w, int h, float depth, int start, int end) */ 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(PREFIX_E "load_system_font: Nameless font\n"); 00536 return NULL; 00537 } 00538 00539 /* Load a system font */ 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 XLOCK(); 00546 ret = x_load_system_font(name, type, style, w, h, depth, start, end); 00547 XUNLOCK(); 00548 #else 00549 /* Other platform */ 00550 #endif 00551 #endif 00552 00553 return ret; 00554 } 00555 00556 00557 00573 void allegro_gl_destroy_font(FONT *f) { 00574 00575 FONT_AGL_DATA *data; 00576 00577 if (!f) { 00578 return; 00579 } 00580 if (f->vtable != font_vtable_agl) { 00581 TRACE(PREFIX_E "destroy_font: Font is not of AGL type\n"); 00582 return; 00583 } 00584 00585 data = f->data; 00586 00587 if (!data) { 00588 TRACE(PREFIX_E "destroy_font: Font is inconsistent\n"); 00589 return; 00590 } 00591 00592 /* Iterate through every segment of the font */ 00593 while (data) { 00594 FONT_AGL_DATA *datanext; 00595 00596 /* Release all resources taken up by this font */ 00597 if (data->type == AGL_FONT_TYPE_BITMAP 00598 || data->type == AGL_FONT_TYPE_OUTLINE 00599 || data->type == AGL_FONT_TYPE_TEXTURED) { 00600 00601 if (__allegro_gl_valid_context) { 00602 if (data->list_base) 00603 glDeleteLists(data->list_base, data->end - data->start); 00604 if (data->texture) 00605 glDeleteTextures(1, &data->texture); 00606 } 00607 } 00608 if (data->type == AGL_FONT_TYPE_OUTLINE) { 00609 if (data->data) 00610 free(data->data); 00611 } 00612 else if (data->type == AGL_FONT_TYPE_TEXTURED) { 00613 if (data->data) 00614 destroy_bitmap(data->data); 00615 if (data->glyph_coords) 00616 free(data->glyph_coords); 00617 } 00618 else if (data->type == AGL_FONT_TYPE_BITMAP) { 00619 if (data->data) { 00620 int i; 00621 FONT_GLYPH **gl = data->data; 00622 for (i = 0; i < data->end - data->start; i++) { 00623 if (gl[i]) 00624 free(gl[i]); 00625 } 00626 free(gl); 00627 } 00628 } 00629 datanext = data->next; 00630 00631 if (data->is_free_chunk) 00632 free(data); 00633 00634 data = datanext; 00635 } 00636 free(f->data); 00637 00638 if (f != font) 00639 free(f); 00640 00641 return; 00642 } 00643 00644 00645 00646 /* size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) */ 00689 size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) { 00690 00691 size_t num_ids = 0; 00692 FONT_AGL_DATA *data; 00693 00694 if (!f) { 00695 return 0; 00696 } 00697 if (f->vtable != font_vtable_agl) { 00698 TRACE(PREFIX_E "list_font_textures: Font is not of AGL type\n"); 00699 return 0; 00700 } 00701 00702 data = f->data; 00703 00704 if (!data) { 00705 TRACE(PREFIX_E "list_font_textures: Font is inconsistent\n"); 00706 return 0; 00707 } 00708 00709 if (!__allegro_gl_valid_context) { 00710 return 0; 00711 } 00712 00713 /* Iterate through all font segments */ 00714 while (data) { 00715 if (data->texture) { 00716 /* Add the texture ID in the array, if it's not NULL and if there 00717 * is room. 00718 */ 00719 if (ids && num_ids < max_num_id) { 00720 ids[num_ids] = data->texture; 00721 } 00722 num_ids++; 00723 } 00724 00725 data = data->next; 00726 } 00727 00728 return num_ids; 00729 } 00730