aglf.c

Go to the documentation of this file.
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 /* find_range:
00032  *  Searches a font for a specific character.
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 /* allegro_gl_printf(FONT *f, float x, float y, float z, int color,
00049             char *format, ...) */
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     /* Get the string */
00074     va_start(ap, format);
00075         uvszprintf(buf, BUF_SIZE, format, ap);
00076     va_end(ap);
00077 
00078 #undef BUF_SIZE
00079 
00080     /* Set color */
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 /* allegro_gl_printf_ex(FONT *f, float x, float y, float z,
00098  *                      char *format, ...)
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     /* Check arguments */
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     /* Get the string */
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             /* search for a suitable character range */
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         /* Set up texture */
00258         if (d->type == AGL_FONT_TYPE_TEXTURED) {
00259             glBindTexture(GL_TEXTURE_2D, range->texture);
00260         }
00261         
00262         /* draw the character */
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         /* Load the font */
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         /* 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("** ERROR ** 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     ret = x_load_system_font(name, type, style, w, h, depth, start, end);
00546 #else
00547     /* Other platform */
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     /* Iterate through every segment of the font */
00591     while (data) {  
00592         FONT_AGL_DATA *datanext;
00593         
00594         /* Release all resources taken up by this font */
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 /* size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) */
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     /* Iterate through all font segments */
00712     while (data) {
00713         if (data->texture) {
00714             /* Add the texture ID in the array, if it's not NULL and if there
00715              * is room.
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 

Generated on Mon Apr 3 18:20:12 2006 for AllegroGL by  doxygen 1.4.6