Main Page | Modules | File List | Globals | Related Pages

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 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 /* allegro_gl_printf(FONT *f, float x, float y, float z, int color,
00049             char *format, ...) */
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     /* Check arguments */
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     /* Get the string */
00153     va_start(ap, format);
00154         uvsprintf(buf, format, ap);
00155     va_end(ap);
00156 
00157 
00158     allegro_gl_begin();
00159 
00160     /* Set color */
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             /* search for a suitable character range */
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         /* Set up texture */
00216         if (d->type == AGL_FONT_TYPE_TEXTURED) {
00217             glBindTexture(GL_TEXTURE_2D, range->texture);
00218         }
00219         
00220         /* draw the character */
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         /* Load the font */
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         /* Not Yet Implemented */
00398         return NULL;
00399     }
00400     
00401     return ret;
00402 }
00403 #endif
00404 #endif /* ALLEGROGL_GENERIC_DRIVER */
00405 
00406 
00407 
00408 /* void allegro_gl_set_font_generation_mode(int mode) */
00423 void allegro_gl_set_font_generation_mode(int mode) {
00424     aglf_font_generation_mode = mode;
00425     return;
00426 }
00427 
00428 
00429 
00430 /* FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) */
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 /* FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
00448             int w, int h, float depth, int start, int end) */
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     /* Load a system font */
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     /* Other platform */
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     /* Iterate through every segment of the font */
00545     while (data) {  
00546         FONT_AGL_DATA *datanext;
00547         
00548         /* Release all resources taken up by this font */
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 /* size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) */
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     /* Iterate through all font segments */
00664     while (data) {
00665         if (data->texture) {
00666             /* Add the texture ID in the array, if it's not NULL and if there
00667              * is room.
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 

Generated on Wed Jun 30 23:59:52 2004 for AllegroGL by doxygen 1.3.5