aglf.c

Go to the documentation of this file.
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     allegro_gl_begin();
00212 
00213     glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
00214     glGetIntegerv(GL_FRONT_FACE, &vert_order);
00215     glGetIntegerv(GL_CULL_FACE_MODE, &cull_mode);   
00216     
00217     glMatrixMode(GL_MODELVIEW);
00218     glPushMatrix();
00219     
00220     glFrontFace(GL_CW);
00221     glCullFace(GL_BACK);
00222 
00223     {   GLint temp;
00224         glGetIntegerv(GL_TEXTURE_BINDING_2D, &temp);
00225         old_texture_bind = (GLuint)temp;
00226     }
00227 
00228     if (d->type == AGL_FONT_TYPE_BITMAP) {
00229         glTranslatef(0, 0, -1);
00230         glBindTexture(GL_TEXTURE_2D, 0);
00231         
00232         glGetFloatv(GL_CURRENT_RASTER_POSITION, old_raster_pos);
00233         glRasterPos2f(x, y);
00234         restore_rasterpos = 1;
00235     }
00236     else if (d->type == AGL_FONT_TYPE_OUTLINE) {
00237         glTranslatef(x, y, z);
00238         glBindTexture(GL_TEXTURE_2D, 0);
00239     }
00240     else if (d->type == AGL_FONT_TYPE_TEXTURED) {
00241         glTranslatef(x, y, z);
00242     }
00243 
00244 
00245     while ((c = ugetc(buf + pos)) != 0) {
00246 
00247         pos += ucwidth(c);
00248 
00249         if ((!range) || (c < range->start) || (c >= range->end)) {
00250             /* search for a suitable character range */
00251             range = find_range(d, c);
00252 
00253             if (!range) {
00254                 range = find_range(d, (c = '^'));
00255 
00256                 if (!range)
00257                     continue;
00258             }
00259         }
00260         
00261         /* Set up texture */
00262         if (d->type == AGL_FONT_TYPE_TEXTURED) {
00263             glBindTexture(GL_TEXTURE_2D, range->texture);
00264         }
00265         
00266         /* draw the character */
00267         c -= range->start;
00268         c += range->list_base;
00269         
00270         glCallList(c);
00271 
00272         count++;
00273     }
00274     
00275     glPopMatrix();
00276 
00277     glMatrixMode(matrix_mode);
00278     glFrontFace(vert_order);
00279     glCullFace(cull_mode);  
00280 
00281     glBindTexture(GL_TEXTURE_2D, old_texture_bind);
00282 
00283     if (restore_rasterpos) {
00284         glRasterPos4fv(old_raster_pos);
00285     }
00286 
00287     allegro_gl_end();
00288     
00289     return count;
00290 }
00291 
00292 
00293 
00294 #ifndef ALLEGROGL_GENERIC_DRIVER
00295 #ifdef ALLEGRO_WINDOWS
00296 
00297 static FONT *win_load_system_font(char *name, int type, int style, int w, int h, float depth, int start, int end) {
00298 
00299     HFONT hFont;
00300 
00301     FONT_AGL_DATA *data;
00302     FONT *ret;
00303     
00304     ret = malloc(sizeof(FONT));
00305     if (!ret) {
00306         TRACE(PREFIX_E "win_load_system_font: Ran out of memory "
00307               "while allocating %i bytes\n", sizeof(FONT));
00308         return NULL;
00309     }
00310     data = malloc(sizeof(FONT_AGL_DATA));
00311     if (!data) {
00312         free(ret);
00313         TRACE(PREFIX_E "win_load_system_font: Ran out of memory "
00314               "while allocating %i bytes\n", sizeof(FONT_AGL_DATA));
00315         return NULL;
00316     }
00317     ret->vtable = font_vtable_agl;
00318     ret->data = data;
00319         
00320     data->list_base = glGenLists(end - start);
00321     data->start = start;
00322     data->end = end;
00323     data->next = NULL;
00324     data->is_free_chunk = 0;
00325 
00326     if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
00327 
00328         HDC dc;
00329 
00330         hFont = CreateFont( -h, w,
00331             0, 0,
00332             (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
00333                      : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
00334             ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
00335             ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
00336             ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
00337             ANSI_CHARSET,
00338             OUT_TT_PRECIS,
00339             CLIP_DEFAULT_PRECIS,
00340             (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
00341                      : DEFAULT_QUALITY,
00342             FF_DONTCARE | DEFAULT_PITCH,
00343             name);
00344 
00345         dc = GetDC(win_get_window());
00346 
00347         SelectObject(dc, hFont);
00348 
00349         wglUseFontBitmaps(dc, start, end - start, data->list_base);
00350         data->type = AGL_FONT_TYPE_BITMAP;
00351         data->data = NULL;
00352     }
00353     else if (type == AGL_FONT_TYPE_OUTLINE) {
00354         HDC dc;
00355 
00356         GLYPHMETRICSFLOAT *gmf;
00357         gmf = malloc(sizeof(GLYPHMETRICSFLOAT) * (end - start));
00358         memset(gmf, 0, sizeof(GLYPHMETRICSFLOAT) * (end - start));
00359 
00360         hFont = CreateFont( -h, w,
00361             0, 0,
00362             (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
00363                       : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
00364             ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
00365             ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
00366             ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
00367             ANSI_CHARSET,
00368             OUT_TT_PRECIS,
00369             CLIP_DEFAULT_PRECIS,
00370             (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
00371                       : DEFAULT_QUALITY,
00372             FF_DONTCARE | DEFAULT_PITCH,
00373             name);
00374 
00375         dc = GetDC(win_get_window());
00376 
00377         SelectObject(dc, hFont);
00378         wglUseFontOutlines(dc, start, end - start, data->list_base,
00379             0.0, depth, (aglf_font_generation_mode == AGL_FONT_POLYGONS)
00380             ? WGL_FONT_POLYGONS : WGL_FONT_LINES, gmf);
00381 
00382         data->type = AGL_FONT_TYPE_OUTLINE;
00383         data->data = gmf;
00384     }
00385 
00386     return ret;
00387 }
00388 #endif
00389 
00390 
00391 
00392 #ifdef ALLEGRO_WITH_XWINDOWS
00393 static FONT *x_load_system_font(char *name, int type, int style, int w, int h,
00394                                               float depth, int start, int end) {
00395     FONT_AGL_DATA *data;
00396     FONT *ret;
00397     XFontStruct *xfont;
00398 
00399     ret = malloc(sizeof(FONT));
00400     if (!ret) {
00401         TRACE(PREFIX_E "x_load_system_font: Ran out of memory "
00402               "while allocating %i bytes\n", sizeof(FONT));
00403         return NULL;
00404     }
00405     data = malloc(sizeof(FONT_AGL_DATA));
00406     if (!data) {
00407         free(ret);
00408         TRACE(PREFIX_E "x_load_system_font: Ran out of memory "
00409               "while allocating %i bytes\n", sizeof(FONT_AGL_DATA));
00410         return NULL;
00411     }
00412     ret->vtable = font_vtable_agl;
00413     ret->data = data;
00414         
00415     data->list_base = glGenLists(end - start);
00416     data->start = start;
00417     data->end = end;
00418     data->next = NULL;
00419     data->is_free_chunk = 0;
00420 
00421     if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
00422         char buf[256], major_type[256], minor_type[2];
00423         
00424         usprintf(major_type, "medium");
00425         if (style & AGL_FONT_STYLE_BOLD)
00426             usprintf(major_type, "bold");
00427         minor_type[0] = (style & AGL_FONT_STYLE_ITALIC) ? 'i' : 'r';
00428         minor_type[1] = '\0';
00429         
00430         usprintf(buf, "-*-%s-%s-%s-normal-*-%i-*-*-*-*-*-*-*", name,
00431                                                     major_type, minor_type, h);
00432         /* Load the font */
00433         xfont = XLoadQueryFont(_xwin.display, buf);
00434         if (!xfont) {
00435             free(ret);
00436             free(data);
00437             TRACE(PREFIX_E "x_load_system_font: Failed to load "
00438                   "%s\n", buf);
00439             return NULL;
00440         }
00441         glXUseXFont(xfont->fid, start, end - start, data->list_base);
00442         data->type = AGL_FONT_TYPE_BITMAP;
00443         data->data = NULL;
00444         XFreeFont(_xwin.display, xfont);
00445     }
00446     else {
00447         /* Not Yet Implemented */
00448         return NULL;
00449     }
00450     
00451     return ret;
00452 }
00453 #endif
00454 #endif /* ALLEGROGL_GENERIC_DRIVER */
00455 
00456 
00457 
00458 /* void allegro_gl_set_font_generation_mode(int mode) */
00473 void allegro_gl_set_font_generation_mode(int mode) {
00474     aglf_font_generation_mode = mode;
00475     return;
00476 }
00477 
00478 
00479 
00480 /* FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) */
00489 FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) {
00490 
00491     return allegro_gl_load_system_font_ex(name, AGL_FONT_TYPE_OUTLINE,
00492                                           style, w, h, 0.0f, 32, 256);
00493 }
00494 
00495 
00496 
00497 /* FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
00498             int w, int h, float depth, int start, int end) */
00530 FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
00531                                 int w, int h, float depth, int start, int end) {
00532 
00533     FONT *ret = NULL;
00534 
00535     if (!__allegro_gl_valid_context)
00536         return NULL;
00537 
00538     if (!name) {
00539         TRACE(PREFIX_E "load_system_font: Nameless font\n");
00540         return NULL;
00541     }
00542 
00543     /* Load a system font */
00544 
00545 #ifndef ALLEGROGL_GENERIC_DRIVER
00546 #ifdef ALLEGRO_WINDOWS
00547     ret = win_load_system_font(name, type, style, w, h, depth, start, end);
00548 #elif defined ALLEGRO_UNIX
00549     XLOCK();
00550     ret = x_load_system_font(name, type, style, w, h, depth, start, end);
00551     XUNLOCK();
00552 #else
00553     /* Other platform */
00554 #endif
00555 #endif
00556 
00557     return ret;
00558 }
00559 
00560 
00561 
00577 void allegro_gl_destroy_font(FONT *f) {
00578 
00579     FONT_AGL_DATA *data;
00580 
00581     if (!f) {
00582         return;
00583     }
00584     if (f->vtable != font_vtable_agl) {
00585         TRACE(PREFIX_E "destroy_font: Font is not of AGL type\n");  
00586         return;
00587     }
00588     
00589     data = f->data;
00590     
00591     if (!data) {
00592         TRACE(PREFIX_E "destroy_font: Font is inconsistent\n"); 
00593         return;
00594     }
00595 
00596     /* Iterate through every segment of the font */
00597     while (data) {  
00598         FONT_AGL_DATA *datanext;
00599         
00600         /* Release all resources taken up by this font */
00601         if (data->type == AGL_FONT_TYPE_BITMAP
00602          || data->type == AGL_FONT_TYPE_OUTLINE
00603          || data->type == AGL_FONT_TYPE_TEXTURED) {
00604 
00605             if (__allegro_gl_valid_context) {
00606                 if (data->list_base)
00607                     glDeleteLists(data->list_base, data->end - data->start);
00608                 if (data->texture)
00609                     glDeleteTextures(1, &data->texture);
00610             }
00611         }
00612         if (data->type == AGL_FONT_TYPE_OUTLINE) {
00613             if (data->data) 
00614                 free(data->data);
00615         }
00616         else if (data->type == AGL_FONT_TYPE_TEXTURED) {
00617             if (data->data)
00618                 destroy_bitmap(data->data);
00619             if (data->glyph_coords)
00620                 free(data->glyph_coords);
00621         }
00622         else if (data->type == AGL_FONT_TYPE_BITMAP) {
00623             if (data->data) {
00624                 int i;
00625                 FONT_GLYPH **gl = data->data;
00626                 for (i = 0; i < data->end - data->start; i++) {
00627                     if (gl[i])
00628                         free(gl[i]);
00629                 }
00630                 free(gl);
00631             }
00632         }
00633         datanext = data->next;
00634 
00635         if (data->is_free_chunk)
00636             free(data);
00637             
00638         data = datanext;
00639     }
00640     free(f->data);
00641 
00642     if (f != font)
00643         free(f);
00644     
00645     return;
00646 }
00647 
00648 
00649 
00650 /* size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) */
00693 size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) {
00694 
00695     size_t num_ids = 0;
00696     FONT_AGL_DATA *data;
00697 
00698     if (!f) {
00699         return 0;
00700     }
00701     if (f->vtable != font_vtable_agl) {
00702         TRACE(PREFIX_E "list_font_textures: Font is not of AGL type\n");    
00703         return 0;
00704     }
00705     
00706     data = f->data;
00707     
00708     if (!data) {
00709         TRACE(PREFIX_E "list_font_textures: Font is inconsistent\n");   
00710         return 0;
00711     }
00712 
00713     if (!__allegro_gl_valid_context) {
00714         return 0;
00715     }
00716 
00717     /* Iterate through all font segments */
00718     while (data) {
00719         if (data->texture) {
00720             /* Add the texture ID in the array, if it's not NULL and if there
00721              * is room.
00722              */
00723             if (ids && num_ids < max_num_id) {
00724                 ids[num_ids] = data->texture;
00725             }
00726             num_ids++;
00727         }
00728 
00729         data = data->next;
00730     }
00731     
00732     return num_ids;
00733 }
00734 

Generated on Sun Dec 3 18:06:49 2006 for AllegroGL by  doxygen 1.5.1