AllegroGL: aglf.c Source File

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

# 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     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