Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

glf.cxx

Go to the documentation of this file.
00001 /*
00002 ==============================================================================
00003 |  GLF Library
00004 |  Version 1.4
00005 | 
00006 |  Author: Roman Podobedov
00007 |  Email: romka@ut.ee
00008 |  WEB: http://romka.demonews.com
00009 |  Release Date: 18 May 2001
00010 |  
00011 |  Copyright (C) 2000-2001, Romka Graphics
00012 |  This library is freely distributable without any license or permissions
00013 |  for non-commercial usage. You can use this library in any non-commercial
00014 |  program. In each program, where You use this library You should keep 
00015 |  this header (author name and coordinates)!
00016 |  For commercial usage, please contact me: romka@ut.ee
00017 ==============================================================================
00018 */
00019 
00020 #if defined (WIN32)
00021 #include <windows.h>
00022 #endif
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <math.h>
00028 #include <GL/gl.h>
00029 #include <GL/glu.h>
00030 #include "glf.h"
00031 
00032 /* ---------- Definitions and structures ----- */
00033 
00034 #define MAX_FONTS 256
00035 
00036 /* Color structure */
00037 struct color
00038 {
00039         float r, g, b, a;
00040 };
00041 
00042 /* One symbol of font */
00043 struct one_symbol
00044 {
00045         unsigned char vertexs; /* Number of vertexs         */
00046         unsigned char facets;  /* Number of facets          */
00047         unsigned char lines;   /* Number of lines in symbol */
00048 
00049         float *vdata;          /* Pointer to Vertex data    */
00050         unsigned char *fdata;  /* Pointer to Facets data    */
00051         unsigned char *ldata;  /* Pointer to Line data      */
00052 
00053         float leftx;           /* Smaller x coordinate      */
00054         float rightx;          /* Right x coordinate        */
00055         float topy;            /* Top y coordinate          */
00056         float bottomy;         /* Bottom y coordinate       */
00057 };
00058 
00059 /* Font structure */
00060 struct glf_font
00061 {
00062         char font_name [97];
00063         unsigned char sym_total;          /* Total symbols in font */
00064         struct one_symbol *symbols[256];  /* Pointers to symbols   */
00065 };
00066 
00067 /* ------------- Main variables -------------- */
00068 
00069 static float SymbolDist = 0.2f;  /* Distance between symbols (Variable constant) */
00070 static float SymbolDepth = 0.2f; /* Symbol Depth in 3D space (Variable constant) */
00071 static float SpaceSize = 2.0f;   /* Space size (Variable constant)               */
00072 static float RotateAngle = 0.0f; /* Rotate angle for string (vector font) */
00073 static float RotateAngleB = 0.0f; /* Rotate angle for string (bitmap font) */
00074 
00075 /* Array of font pointers, up to MAX_FONTS fonts can be loaded at once */
00076 /* if (fonts[i] == NULL) then this font is not present in memory */
00077 
00078 static struct   glf_font *fonts[MAX_FONTS];
00079 static int              curfont;                        /* Index of current font pointer */
00080 static char             ap = GLF_CENTER;        /* Anchor point */
00081 static GLboolean m_string_center;       /* String centering (vector fonts) */
00082 static GLboolean m_bitmap_string_center;        /* String centering (bitmap fonts) */
00083 
00084 static GLuint   m_direction;    /* String direction (vector fonts) */
00085 
00086 static char             console_msg = GLF_NO;
00087 static char             texturing = GLF_NO;
00088 static char             contouring = GLF_NO;
00089 static struct   color contouring_color;
00090 
00091 /* Console mode variables */
00092 static int      conWidth, conHeight;    /* Console width and height */
00093 static int      conx = 0, cony = 0;             /* Console current X and Y */
00094 static char     *conData;                               /* Console data */
00095 static int      conFont;                                /* Console font */
00096 static char     conCursor = GLF_NO;             /* Console cursor Enabled|Disabled */
00097 static int      conCursorBlink;         /* Console cursor blink rate */
00098 static int      conCursorCount;         /* Console cursor blink counter */
00099 static char     conCursorMode = GLF_NO; /* Console Cursor mode (on/off screen) */
00100 
00101 /* ----------- Variables for bitmap font ------------- */
00102 #define SEEK_SET_POS 4195
00103 
00104 struct coord_rect
00105 {
00106         float x, y, width, height;
00107 };
00108 
00109 struct widths
00110 {
00111         float *width;
00112 };
00113 
00114 /* Constants */
00115 static float sym_space=0.001f;
00116 
00117 /* One font variables */
00118 static struct coord_rect Symbols[256];
00119 static GLboolean bmf_texturing;
00120 static int    bmf_curfont;
00121 static GLuint bmf_texture[MAX_FONTS]; /* All fonts */
00122 static GLuint bmf_mask[MAX_FONTS]; /* All fonts (masked) */
00123 static char       bmf_in_use[MAX_FONTS]; /* 1 - if font is used, 0 - otherwise */
00124 static int        list_base[MAX_FONTS];
00125 static GLfloat m_max_height[MAX_FONTS]; /* Maximal height of each font */
00126 static struct widths m_widths[MAX_FONTS]; /* Width of each symbols in each font */
00127 
00128 
00129 /* Initialization of GLF library, should be called before use of library */
00130 void glfInit()
00131 {
00132         int i;
00133 
00134         for (i=0; i<MAX_FONTS; i++)
00135         {
00136                 fonts[i] = NULL;
00137                 bmf_in_use[i] = 0;
00138                 m_max_height[i] = 0;
00139         }
00140         
00141         curfont = -1;
00142         bmf_curfont = -1;
00143         console_msg = GLF_NO;
00144         ap = GLF_CENTER;                /* Set anchor point to center of each symbol */
00145         texturing = GLF_NO;             /* By default texturing is NOT Enabled */
00146         contouring = GLF_NO;    /* By default contouring is NOT Enabled */
00147         memset(&contouring_color, 0, sizeof(struct color));
00148         conData = NULL;
00149         glfSetConsoleParam(40, 20);
00150         glfConsoleClear();
00151         glfEnable(GLF_CONSOLE_CURSOR);
00152         glfSetCursorBlinkRate(10);
00153         glfStringCentering(GL_FALSE);
00154         glfBitmapStringCentering(GL_FALSE);
00155         glfStringDirection(GLF_LEFT);
00156 }
00157 
00158 /* Closing library usage */
00159 void glfClose()
00160 {
00161         int i;
00162         
00163         free(conData);
00164 
00165         for (i=0; i<MAX_FONTS; i++) glfUnloadFontD(i);
00166         for (i=0; i<MAX_FONTS; i++) glfUnloadBMFFontD(i);
00167 }
00168 
00169 /* 
00170 |       This function check that this machine is little endian
00171 |       Return value:   1 - little endian
00172 |                                       0 - big endian
00173 */
00174 static int LittleEndian()
00175 {
00176         int endianTester = 1;
00177         char *endianChar = 0;
00178 
00179         endianChar = (char *)&endianTester;
00180         if (*endianChar) return 1;
00181         return 0;
00182 }
00183 
00184 
00185 /*
00186    --------------------------------------------------------------------------------- 
00187    ------------------------ Work with vector fonts --------------------------------- 
00188    --------------------------------------------------------------------------------- 
00189 */
00190 
00191 /* 
00192 |       This function read font file and store information in memory
00193 |       Return: GLF_OK - if all OK
00194 |       Return: GLF_ERROR - if any error 
00195 */
00196 static int ReadFont(char *font_name, struct glf_font *glff)
00197 {
00198 
00199         FILE *fontf;
00200         char buffer[64];
00201         int i, j;
00202         unsigned char temp, code, verts, fcets, lns;
00203         float tempfx, tempfy;
00204         unsigned char *tp;
00205         int LEndian; /* True if little endian machine */
00206 
00207         fontf = fopen(font_name, "rb");
00208         if (fontf == NULL) return GLF_ERROR;
00209 
00210         fread(buffer, 3, 1, fontf);
00211         buffer[3] = 0;
00212         if (strcmp(buffer, "GLF"))
00213         {
00214                 /* If header is not "GLF" */
00215                 if (console_msg) printf("Error reading font file: incorrect file format\n");
00216                 return GLF_ERROR;
00217         }
00218 
00219         /* Check for machine type */
00220         LEndian = LittleEndian();
00221 
00222         fread(glff->font_name, 96, 1, fontf);
00223         glff->font_name[96] = 0;
00224 
00225         fread(&glff->sym_total, 1, 1, fontf); /* Read total symbols in font */
00226 
00227         for (i=0; i<MAX_FONTS; i++) glff->symbols[(int)i] = NULL;
00228 
00229         for (i=0; i<28; i++) fread(&temp, 1, 1, fontf);  /* Read unused data */
00230 
00231         /* Now start to read font data */
00232   
00233         for (i=0; i<glff->sym_total; i++)
00234         {
00235                 fread(&code, 1, 1, fontf);  /* Read symbol code   */
00236                 fread(&verts, 1, 1, fontf); /* Read vertexs count */
00237                 fread(&fcets, 1, 1, fontf); /* Read facets count  */
00238                 fread(&lns, 1, 1, fontf);   /* Read lines count   */
00239 
00240                 if (glff->symbols[(int)code] != NULL) 
00241                 {
00242                         if (console_msg) printf("Error reading font file: encountered symbols in font\n");
00243                         return GLF_ERROR;
00244                 }
00245 
00246                 glff->symbols[(int)code] = (struct one_symbol *)malloc(sizeof(struct one_symbol));
00247                 glff->symbols[(int)code]->vdata = (float *)malloc(8*verts);
00248                 glff->symbols[(int)code]->fdata = (unsigned char *)malloc(3*fcets);
00249                 glff->symbols[(int)code]->ldata = (unsigned char *)malloc(lns);
00250 
00251                 glff->symbols[(int)code]->vertexs = verts;
00252                 glff->symbols[(int)code]->facets = fcets;
00253                 glff->symbols[(int)code]->lines = lns;
00254 
00255                 /* Read vertexs data */
00256                 glff->symbols[(int)code]->leftx = 10;
00257                 glff->symbols[(int)code]->rightx = -10;
00258                 glff->symbols[(int)code]->topy = 10;
00259                 glff->symbols[(int)code]->bottomy = -10;
00260 
00261                 for (j=0; j<verts; j++)
00262                 {
00263                         fread(&tempfx, 4, 1, fontf);
00264                         fread(&tempfy, 4, 1, fontf);
00265           
00266                         /* If machine is bigendian -> swap low and high words in
00267                         tempfx and tempfy */
00268                         if (!LEndian) 
00269                         {
00270                                 tp = (unsigned char *)&tempfx;
00271                                 temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
00272                                 temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
00273                                 tp = (unsigned char *)&tempfy;
00274                                 temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
00275                                 temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
00276                         }
00277                         glff->symbols[(int)code]->vdata[j*2] = tempfx;
00278                         glff->symbols[(int)code]->vdata[j*2+1] = tempfy;
00279 
00280                         if (tempfx < glff->symbols[(int)code]->leftx) glff->symbols[(int)code]->leftx = tempfx;
00281                         if (tempfx > glff->symbols[(int)code]->rightx) glff->symbols[(int)code]->rightx = tempfx;
00282                         if (tempfy < glff->symbols[(int)code]->topy) glff->symbols[(int)code]->topy = tempfy;
00283                         if (tempfy > glff->symbols[(int)code]->bottomy) glff->symbols[(int)code]->bottomy = tempfy;
00284                 }
00285                 for (j=0; j<fcets; j++)
00286                         fread(&glff->symbols[(int)code]->fdata[j*3], 3, 1, fontf);
00287                 for (j=0; j<lns; j++)
00288                         fread(&glff->symbols[(int)code]->ldata[j], 1, 1, fontf);
00289         }
00290         fclose(fontf);
00291         return GLF_OK;
00292 }
00293 
00294 
00295 /* 
00296 | Function loads font to memory from file
00297 | Return value: GLF_ERROR  - if error
00298 |               >=0 - returned font descriptor (load success)
00299 */
00300 int glfLoadFont(char *font_name)
00301 {
00302         int i;
00303         char flag; /* Temporary flag */
00304 
00305         /* First we find free font descriptor */
00306         flag = 0; /* Descriptor not found yet */
00307         for (i=0; i<MAX_FONTS; i++)
00308                 if (fonts[i] == NULL)
00309                 {
00310                         /* Initialize this font */
00311                         fonts[i] = (struct glf_font *)malloc(sizeof(struct glf_font));
00312                         flag = 1;
00313                         break;
00314                 }
00315 
00316         if (!flag) return GLF_ERROR; /* Free font not found */
00317         if (ReadFont(font_name, fonts[i]) == GLF_OK) 
00318         {
00319                 curfont = i; /* Set curfont to just loaded font */
00320                 return i;
00321         }
00322   
00323         if (fonts[i] != NULL)
00324         {
00325                 free(fonts[i]);
00326                 fonts[i] = NULL;
00327         }
00328         return GLF_ERROR;
00329 }
00330 
00331 /* 
00332 | Unload current font from memory
00333 | Return value: GLF_OK  - if all OK
00334 |               GLF_ERROR -  if error
00335 */
00336 int glfUnloadFont()
00337 {
00338         int i;
00339   
00340         if ((curfont<0) || (fonts[curfont] == NULL)) return GLF_ERROR;
00341   
00342         for (i=0; i<256; i++)
00343         {
00344                 if (fonts[curfont]->symbols[(int)i] != NULL)
00345                 {
00346                         free(fonts[curfont]->symbols[(int)i]->vdata);
00347                         free(fonts[curfont]->symbols[(int)i]->fdata);
00348                         free(fonts[curfont]->symbols[(int)i]->ldata);
00349                         free(fonts[curfont]->symbols[(int)i]);
00350                 }
00351         }
00352 
00353         free(fonts[curfont]);
00354         fonts[curfont] = NULL;
00355         curfont = -1;
00356         return GLF_OK;
00357 }
00358 
00359 /* Unload font by font descriptor */
00360 int glfUnloadFontD(int font_descriptor)
00361 {
00362         int temp;
00363 
00364         if ((font_descriptor < 0) || (fonts[font_descriptor] == NULL)) return GLF_ERROR;
00365 
00366         temp = curfont;
00367         curfont = font_descriptor;
00368         glfUnloadFont();
00369         if (temp != font_descriptor) curfont = temp;
00370         else curfont = -1;
00371         return GLF_OK;
00372 }
00373 
00374 void glfDrawWiredSymbol(char s)
00375 {
00376         int i, cur_line;
00377         float *tvp; /* temporary vertex pointer */
00378         float x, y;
00379   
00380         if ((curfont < 0) || (fonts[curfont] == NULL)) return;
00381         if (fonts[curfont]->symbols[(int)s] == NULL) return;
00382 
00383         glBegin(GL_LINE_LOOP);
00384         tvp = fonts[curfont]->symbols[(int)s]->vdata;
00385         cur_line = 0;
00386         for (i=0; i<fonts[curfont]->symbols[(int)s]->vertexs; i++)
00387         {
00388                 x = *tvp++;
00389                 y = *tvp++;
00390                 glVertex2f(x, y);
00391                 if (fonts[curfont]->symbols[(int)s]->ldata[cur_line] == i)
00392                 {
00393                         glEnd();
00394                         cur_line++;
00395                         if (cur_line < fonts[curfont]->symbols[(int)s]->lines) glBegin(GL_LINE_LOOP);
00396                         else break; /* No more lines */
00397                 }
00398         }
00399 }
00400 
00401 /* Draw wired symbol by font_descriptor */
00402 void glfDrawWiredSymbolF(int font_descriptor, char s)
00403 {
00404         int temp;
00405 
00406         temp = curfont;
00407         curfont = font_descriptor;
00408         glfDrawWiredSymbol(s);
00409         curfont = temp;
00410 }
00411 
00412 static void DrawString(char *s, void (*funct) (char s))
00413 {
00414         int i;
00415         float sda, sdb;
00416         float distance = 0;
00417 
00418         if (!s) return;
00419         if (!*s) return;
00420         if (curfont == -1) return;
00421 
00422         /* Calculate correction (if string centering enabled) */
00423         if (m_string_center)
00424         {
00425                 distance = 0;
00426                 for (i=0; i<(int)strlen(s); i++)
00427                 {
00428                         if ((fonts[curfont]->symbols[(int)s[i]] == NULL) || (s[i] == ' ')) 
00429                         {
00430                                 if (m_direction == GLF_LEFT || m_direction == GLF_UP) distance += SpaceSize;
00431                                 else distance -= SpaceSize;
00432                         }
00433                         else
00434                                 if (i < ((int)strlen(s)-1))
00435                                         if (s[i+1] == ' ') 
00436                                         {
00437                                                 if (m_direction == GLF_LEFT || m_direction == GLF_UP) distance += SymbolDist;
00438                                                 else distance -= SymbolDist;
00439                                         }
00440                                         else
00441                                         {
00442                                                 if (fonts[curfont]->symbols[(int)s[i+1]] == NULL) continue;
00443         
00444                                                 if (m_direction == GLF_LEFT || m_direction == GLF_RIGHT)
00445                                                 {
00446                                                         sda = (float)fabs(fonts[curfont]->symbols[(int)s[i]]->rightx);
00447                                                         sdb = (float)fabs(fonts[curfont]->symbols[(int)s[i+1]]->leftx);
00448                                                         if (m_direction == GLF_LEFT) distance += sda+sdb+SymbolDist;
00449                                                         else distance -= sda+sdb+SymbolDist;
00450                                                 }
00451                                                 else
00452                                                 {
00453                                                         sda = (float)fabs(fonts[curfont]->symbols[(int)s[i]]->topy);
00454                                                         sdb = (float)fabs(fonts[curfont]->symbols[(int)s[i]]->bottomy);
00455                                                         if (m_direction == GLF_DOWN) distance -= sda+sdb+SymbolDist;
00456                                                         else distance += sda+sdb+SymbolDist;
00457                                                 }
00458                                         }
00459                 }
00460         }
00461 
00462         glPushMatrix();
00463         
00464         /* Rotate if needed */
00465         if (RotateAngle != 0.0f) glRotatef(RotateAngle, 0, 0, 1);
00466 
00467         /* Correct string position */
00468         if (m_string_center)
00469         {
00470                 switch (m_direction)
00471                 {
00472                         case GLF_LEFT : glTranslatef(-distance/2, 0, 0); break;
00473                         case GLF_RIGHT : glTranslatef(distance/2, 0, 0); break;
00474                         case GLF_UP : glTranslatef(0, distance/2, 0); break;
00475                         case GLF_DOWN : glTranslatef(0, -distance/2, 0); break;
00476                 }
00477         }
00478         else if (s[0] != ' ')
00479         {
00480                 switch (m_direction)
00481                 {
00482                         case GLF_LEFT : glTranslatef(-(1-(float)fabs(fonts[curfont]->symbols[(int)s[0]]->leftx)), 0, 0); break;
00483                         case GLF_RIGHT : glTranslatef((1-(float)fabs(fonts[curfont]->symbols[(int)s[0]]->rightx)), 0, 0); break;
00484                         case GLF_UP : glTranslatef(0, (1-(float)fabs(fonts[curfont]->symbols[(int)s[0]]->topy)), 0); break;
00485                         case GLF_DOWN : glTranslatef(0, -(1-(float)fabs(fonts[curfont]->symbols[(int)s[0]]->bottomy)), 0); break;
00486                 }
00487         }
00488 
00489         /* Start to draw our string */
00490         for (i=0; i<(int)strlen(s); i++)
00491         {
00492                 if (s[i] != ' ') (*funct) (s[i]);
00493                 if ((fonts[curfont]->symbols[(int)s[i]] == NULL) || (s[i] == ' '))
00494                 {
00495                         switch (m_direction)
00496                         {
00497                                 case GLF_LEFT : glTranslatef(SpaceSize, 0, 0); break;
00498                                 case GLF_RIGHT : glTranslatef(-SpaceSize, 0, 0); break;
00499                                 case GLF_UP : glTranslatef(0, SpaceSize, 0); break;
00500                                 case GLF_DOWN : glTranslatef(0, -SpaceSize, 0); break;
00501                         }
00502                 }
00503                 else
00504                         if (i < ((int)strlen(s)-1))             
00505                                 if (s[i+1] == ' ') 
00506                                 {
00507                                         switch (m_direction)
00508                                         {
00509                                                 case GLF_LEFT : glTranslatef(SymbolDist, 0, 0); break;
00510                                                 case GLF_RIGHT : glTranslatef(-SymbolDist, 0, 0); break;
00511                                                 case GLF_UP : glTranslatef(0, SymbolDist, 0); break;
00512                                                 case GLF_DOWN : glTranslatef(0, -SymbolDist, 0); break;
00513                                         }
00514                                 }
00515                                 else
00516                                 {
00517                                         if (fonts[curfont]->symbols[(int)s[i+1]] == NULL) continue;
00518                                         
00519                                         if (m_direction == GLF_LEFT || m_direction == GLF_RIGHT)
00520                                         {
00521                                                 if (m_direction == GLF_LEFT)
00522                                                 {
00523                                                         sda = (float)fabs(fonts[curfont]->symbols[(int)s[i]]->rightx);
00524                                                         sdb = (float)fabs(fonts[curfont]->symbols[(int)s[i+1]]->leftx);
00525                                                 }
00526                                                 else
00527                                                 {
00528                                                         sda = (float)fabs(fonts[curfont]->symbols[(int)s[i+1]]->rightx);
00529                                                         sdb = (float)fabs(fonts[curfont]->symbols[(int)s[i]]->leftx);
00530                                                 }
00531                                         
00532                                                 if (m_direction == GLF_LEFT) glTranslatef(sda+sdb+SymbolDist, 0, 0);
00533                                                 else glTranslatef(-(sda+sdb+SymbolDist), 0, 0);
00534                                         }
00535                                         else
00536                                         {
00537                                                 if (m_direction == GLF_DOWN) 
00538                                                 {
00539                                                         sda = (float)fabs(fonts[curfont]->symbols[(int)s[i]]->topy);
00540                                                         sdb = (float)fabs(fonts[curfont]->symbols[(int)s[i+1]]->bottomy);
00541                                                 }
00542                                                 else
00543                                                 {
00544                                                         sda = (float)fabs(fonts[curfont]->symbols[(int)s[i+1]]->topy);
00545                                                         sdb = (float)fabs(fonts[curfont]->symbols[(int)s[i]]->bottomy);         
00546                                                 }
00547                                                 
00548                                                 if (m_direction == GLF_DOWN) glTranslatef(0, -(sda+sdb+SymbolDist), 0);
00549                                                 else glTranslatef(0, sda+sdb+SymbolDist, 0);
00550                                         }
00551                                         
00552                                 }
00553         }
00554         glPopMatrix();
00555 }
00556 
00557 void glfDrawWiredString(char *s)
00558 {
00559         DrawString(s, &glfDrawWiredSymbol);
00560 }
00561 
00562 /* Draw wired string by font_descriptor */
00563 void glfDrawWiredStringF(int font_descriptor, char *s)
00564 {
00565         int temp;
00566 
00567         temp = curfont;
00568         curfont = font_descriptor;
00569         DrawString(s, &glfDrawWiredSymbol);
00570         curfont = temp;
00571 }
00572 
00573 void glfDrawSolidSymbol(char s)
00574 {
00575         unsigned char *b; /* Face pointer   */
00576         float *vp;        /* Vertex pointer */
00577         int i, j;
00578         float x, y;
00579         float temp_color[4];
00580 
00581         if ((curfont<0) || (fonts[curfont] == NULL)) return;
00582   
00583         if (fonts[curfont]->symbols[(int)s] == NULL) return;
00584 
00585         b = fonts[curfont]->symbols[(int)s]->fdata;
00586         vp = fonts[curfont]->symbols[(int)s]->vdata;
00587 
00588         glBegin(GL_TRIANGLES);   
00589         for (i=0; i<fonts[curfont]->symbols[(int)s]->facets; i++)
00590         {
00591                 for (j=0; j<3; j++)
00592                 {
00593                         x = vp[*b*2];
00594                         y = vp[*b*2+1];
00595                         if (texturing == GLF_YES) glTexCoord2f((x+1)/2, (y+1)/2);
00596                         glVertex2f(x, y);
00597                         b++;
00598                 }
00599         }
00600         glEnd();
00601 
00602         /* Draw contour, if enabled */
00603         if (contouring == GLF_YES) 
00604         {
00605                 glGetFloatv(GL_CURRENT_COLOR, temp_color);
00606                 glColor4f(contouring_color.r, contouring_color.g, contouring_color.b, contouring_color.a);
00607                 glfDrawWiredSymbol(s);
00608                 glColor4fv(temp_color);
00609         }
00610 }
00611 
00612 /* Draw solid symbol by font_descriptor */
00613 void glfDrawSolidSymbolF(int font_descriptor, char s)
00614 {
00615         int temp;
00616 
00617         temp = curfont;
00618         curfont = font_descriptor;
00619         glfDrawSolidSymbol(s);
00620         curfont = temp;
00621 }
00622 
00623 void glfDrawSolidString(char *s)
00624 {
00625         DrawString(s, &glfDrawSolidSymbol);
00626 }
00627 
00628 /* Draw solid string by font_descriptor */
00629 void glfDrawSolidStringF(int font_descriptor, char *s)
00630 {
00631         int temp;
00632 
00633         temp = curfont;
00634         curfont = font_descriptor;
00635         DrawString(s, &glfDrawSolidSymbol);
00636         curfont = temp;
00637 }
00638 
00639 
00640 /* ------------ 3D Wired text drawing ---------------------- */
00641 
00642 void glfDraw3DWiredSymbol(char s)
00643 {
00644         int i, cur_line;
00645         float *tvp; /* temp vertex pointer */
00646         float x, y;
00647   
00648         if ((curfont<0) || (fonts[curfont] == NULL)) return;
00649         if (fonts[curfont]->symbols[(int)s] == NULL) return;
00650 
00651         /* Draw front symbol */
00652         glBegin(GL_LINE_LOOP);
00653         tvp = fonts[curfont]->symbols[(int)s]->vdata;
00654         cur_line = 0;
00655         for (i=0; i<fonts[curfont]->symbols[(int)s]->vertexs; i++)
00656         {
00657                 x = *tvp;
00658                 tvp++;
00659                 y = *tvp;
00660                 tvp++;
00661                 glVertex3f(x, y, 1);
00662                 if (fonts[curfont]->symbols[(int)s]->ldata[cur_line] == i)
00663                 {
00664                         glEnd();
00665                         cur_line++;
00666                         if (cur_line < fonts[curfont]->symbols[(int)s]->lines) glBegin(GL_LINE_LOOP);
00667                         else break; /* No more lines */
00668                 }
00669         }
00670 
00671         /* Draw back symbol */
00672         glBegin(GL_LINE_LOOP);
00673         tvp = fonts[curfont]->symbols[(int)s]->vdata;
00674         cur_line = 0;
00675         for (i=0; i<fonts[curfont]->symbols[(int)s]->vertexs; i++)
00676         {
00677                 x = *tvp;
00678             tvp++;
00679                 y = *tvp;
00680                 tvp++;
00681                 glVertex3f(x, y, 1+SymbolDepth);
00682                 if (fonts[curfont]->symbols[(int)s]->ldata[cur_line] == i)
00683                 {
00684                         glEnd();
00685                         cur_line++;
00686                         if (cur_line < fonts[curfont]->symbols[(int)s]->lines) glBegin(GL_LINE_LOOP);
00687                         else break; /* No more lines */
00688                 }
00689         }
00690 
00691         /* Draw lines between back and front symbols */
00692         glBegin(GL_LINES);
00693         tvp = fonts[curfont]->symbols[(int)s]->vdata;
00694         for (i=0; i<fonts[curfont]->symbols[(int)s]->vertexs; i++)
00695         {
00696                 x = *tvp;
00697                 tvp++;
00698                 y = *tvp;
00699                 tvp++;
00700                 glVertex3f(x, y, 1);
00701                 glVertex3f(x, y, 1+SymbolDepth);
00702         }
00703         glEnd();
00704 }
00705 
00706 /* Draw 3D wired symbol by font_descriptor */
00707 void glfDraw3DWiredSymbolF(int font_descriptor, char s)
00708 {
00709         int temp;
00710 
00711         temp = curfont;
00712         curfont = font_descriptor;
00713         glfDraw3DWiredSymbol(s);
00714         curfont = temp;
00715 }
00716 
00717 void glfDraw3DWiredString(char *s)
00718 {
00719         DrawString(s, &glfDraw3DWiredSymbol);
00720 }
00721 
00722 /* Draw 3D wired string by font_descriptor */
00723 void glfDraw3DWiredStringF(int font_descriptor, char *s)
00724 {
00725         int temp;
00726 
00727         temp = curfont;
00728         curfont = font_descriptor;
00729         DrawString(s, &glfDraw3DWiredSymbol);
00730         curfont = temp;
00731 }
00732 
00733 /* ------------ 3D Solid text drawing ---------------------- */
00734 
00735 void glfDraw3DSolidSymbol(char s)
00736 {
00737         int i, j, cur_line, flag;
00738         float x, y, bx=0, by=0;
00739         unsigned char *b; /* Face pointer   */
00740         float *vp;        /* Vertex pointer */
00741         float *tvp;       /* temp vertex pointer */
00742         float temp_color[4];
00743         GLboolean light_temp;
00744   
00745         if ((curfont<0) || (fonts[curfont] == NULL)) return;
00746         if (fonts[curfont]->symbols[(int)s] == NULL) return;
00747 
00748         b = fonts[curfont]->symbols[(int)s]->fdata;
00749         vp = fonts[curfont]->symbols[(int)s]->vdata;
00750 
00751         glBegin(GL_TRIANGLES);   
00752         glNormal3f(0, 0, 1);
00753         for (i=0; i<fonts[curfont]->symbols[(int)s]->facets; i++)
00754         {
00755                 b += 2;
00756                 for (j=0; j<3; j++)
00757                 {
00758                         x = vp[*b*2];
00759                         y = vp[*b*2+1];
00760                         glVertex3f(x, y, 1+SymbolDepth);
00761                         b--;
00762                 }
00763                 b += 4;
00764         }
00765         glEnd();
00766 
00767         b = fonts[curfont]->symbols[(int)s]->fdata;
00768         vp = fonts[curfont]->symbols[(int)s]->vdata;
00769   
00770         glBegin(GL_TRIANGLES);   
00771         glNormal3f(0, 0, -1);
00772         for (i=0; i<fonts[curfont]->symbols[(int)s]->facets; i++)
00773         {
00774                 for (j=0; j<3; j++)
00775                 {
00776                         x = vp[*b*2];
00777                         y = vp[*b*2+1];
00778                         glVertex3f(x, y, 1);
00779                         b++;
00780                 }
00781         }
00782         glEnd();
00783 
00784         flag = 0;
00785         glBegin(GL_QUAD_STRIP);
00786         tvp = fonts[curfont]->symbols[(int)s]->vdata;
00787         cur_line = 0;
00788         for (i=0; i<fonts[curfont]->symbols[(int)s]->vertexs; i++)
00789         {
00790                 x = *tvp;
00791                 tvp++;
00792                 y = *tvp;
00793                 tvp++;
00794                 if (!flag) 
00795                 {
00796                         bx = x;
00797                         by = y;
00798                         flag = 1;
00799                 }
00800                 glNormal3f(x, y, 0);
00801                 glVertex3f(x, y, 1);
00802                 glVertex3f(x, y, 1+SymbolDepth);
00803                 if (fonts[curfont]->symbols[(int)s]->ldata[cur_line] == i)
00804                 {
00805                         glVertex3f(bx, by, 1);
00806                         glVertex3f(bx, by, 1+SymbolDepth);
00807                         flag = 0;
00808                         glEnd();
00809                         cur_line++;
00810                         if (cur_line < fonts[curfont]->symbols[(int)s]->lines) glBegin(GL_QUAD_STRIP);
00811                         else break; /* No more lines */
00812                 }
00813         }
00814 
00815         /* Draw contour, if enabled */
00816         if (contouring == GLF_YES) 
00817         {
00818                 glGetBooleanv(GL_LIGHTING, &light_temp);
00819                 glDisable(GL_LIGHTING);
00820                 glGetFloatv(GL_CURRENT_COLOR, temp_color);
00821                 glColor4f(contouring_color.r, contouring_color.g, contouring_color.b, contouring_color.a);
00822                 glfDraw3DWiredSymbol(s);
00823                 glColor4fv(temp_color);
00824                 if (light_temp) glEnable(GL_LIGHTING);
00825         }
00826 }
00827 
00828 /* Draw 3D solid symbol by font_descriptor */
00829 void glfDraw3DSolidSymbolF(int font_descriptor, char s)
00830 {
00831         int temp;
00832 
00833         temp = curfont;
00834         curfont = font_descriptor;
00835         glfDraw3DSolidSymbol(s);
00836         curfont = temp;
00837 }
00838 
00839 void glfDraw3DSolidString(char *s)
00840 {
00841         DrawString(s, &glfDraw3DSolidSymbol);
00842 }
00843 
00844 /* Draw 3D solid string by font_descriptor */
00845 void glfDraw3DSolidStringF(int font_descriptor, char *s)
00846 {
00847         int temp;
00848 
00849         temp = curfont;
00850         curfont = font_descriptor;
00851         DrawString(s, &glfDraw3DSolidSymbol);
00852         curfont = temp;
00853 }
00854 
00855 /* Get the size a string will have on screen */
00856 void glfGetStringBoundsF(int fd, char *s, float *minx, float *miny, float *maxx, float *maxy)
00857 {
00858         struct glf_font *font;
00859         int i;
00860         float sda, sdb, cw = 0, minxx = 10;
00861         float top = 10, bottom = -10;
00862 
00863         if (fd < 0 || fd > (MAX_FONTS-1)) return;
00864         font = fonts[fd];
00865 
00866         if (font == NULL) return;
00867 
00868         if (font->symbols[(int)s[0]])
00869                 minxx = -(float)(fabs(font->symbols[(int)s[0]]->leftx));
00870         else
00871                 minxx = 0.0;
00872 
00873         for (i=0; i<(int)strlen(s); i++)
00874         {
00875                 if ((font->symbols[(int)s[i]] == NULL) || (s[i] == ' '))
00876                         cw += SpaceSize;
00877                 else
00878                 {
00879                         sdb = (float)fabs(font->symbols[(int)s[i]]->leftx);
00880                         sda = (float)fabs(font->symbols[(int)s[i]]->rightx);
00881 
00882                         cw += sda+sdb+SymbolDist;
00883 
00884                         /* Update top/bottom bounds */
00885                         if (font->symbols[(int)s[i]]->bottomy > bottom)
00886                                 bottom = font->symbols[(int)s[i]]->bottomy;
00887 
00888                         if (font->symbols[(int)s[i]]->topy < top)
00889                                 top = font->symbols[(int)s[i]]->topy;
00890                 }
00891         }
00892 
00893         cw += minxx + SymbolDist;
00894 
00895         if ((maxx) && (maxy))
00896         {
00897                 *maxx = cw;
00898                 *maxy = bottom;
00899         }
00900 
00901         if ((minx) && (miny))
00902         {
00903                 *minx = minxx;
00904                 *miny = top;
00905         }
00906 }
00907 
00908 void glfGetStringBounds(char *s, float *minx, float *miny, float *maxx, float *maxy)
00909 {
00910         glfGetStringBoundsF(curfont, s, minx, miny, maxx, maxy);
00911 }
00912 
00913 void glfSetSymbolSpace(float sp)
00914 {
00915         SymbolDist = sp;
00916 }
00917 
00918 float glfGetSymbolSpace()
00919 {
00920         return SymbolDist;
00921 }
00922 
00923 void glfSetSpaceSize(float sp)
00924 {
00925         SpaceSize = sp;
00926 }
00927 
00928 float glfGetSpaceSize()
00929 {
00930         return SpaceSize;
00931 }
00932 
00933 void glfSetSymbolDepth(float dpth)
00934 {
00935         SymbolDepth = dpth;
00936 }
00937 
00938 float glfGetSymbolDepth()
00939 {
00940         return SymbolDepth;
00941 }
00942 
00943 int glfSetCurrentFont(int Font_Descriptor)
00944 {
00945         if ((Font_Descriptor < 0) || (fonts[Font_Descriptor] == NULL)) return GLF_ERROR;
00946   
00947         curfont = Font_Descriptor;
00948         return GLF_OK;
00949 }
00950 
00951 int glfGetCurrentFont()
00952 {
00953         return curfont;
00954 }
00955 
00956 void glfSetAnchorPoint(int anchp)
00957 {
00958         if ((anchp >= GLF_LEFT_UP) && (anchp <= GLF_RIGHT_DOWN))
00959                 ap = anchp;
00960 }
00961 
00962 void glfSetContourColor(float r, float g, float b, float a)
00963 {
00964         contouring_color.r = r;
00965         contouring_color.g = g;
00966         contouring_color.b = b;
00967         contouring_color.a = a;
00968 }
00969 
00970 void glfEnable(int what)
00971 {
00972         switch (what) 
00973         {
00974                 case GLF_CONSOLE_MESSAGES: console_msg = GLF_YES; break;
00975                 case GLF_TEXTURING: texturing = GLF_YES; break;
00976                 case GLF_CONSOLE_CURSOR: conCursor = GLF_YES; break;
00977                 case GLF_CONTOURING: contouring = GLF_YES; break;
00978         }
00979 }
00980 
00981 void glfDisable(int what)
00982 {
00983         switch (what) 
00984         {
00985                 case GLF_CONSOLE_MESSAGES: console_msg = GLF_NO; break;
00986                 case GLF_TEXTURING: texturing = GLF_NO; break;
00987                 case GLF_CONSOLE_CURSOR: conCursor = GLF_NO; break;
00988                 case GLF_CONTOURING: contouring = GLF_NO; break;
00989         }
00990 }
00991 
00992 /* ---------------- Console functions ---------------------- */
00993 
00994 void glfSetConsoleParam(int width, int height)
00995 {
00996         if (conData) free(conData);
00997 
00998         conWidth = width;
00999         conHeight = height;
01000         conData = (char *)malloc(width*height);
01001         glfConsoleClear();
01002 }
01003 
01004 int glfSetConsoleFont(int Font_Descriptor)
01005 {
01006         if ((Font_Descriptor < 0) || (fonts[Font_Descriptor] == NULL)) return GLF_ERROR;
01007   
01008         conFont = Font_Descriptor;
01009         return GLF_OK;
01010 }
01011 
01012 void glfConsoleClear()
01013 {
01014         memset(conData, 0, conWidth*conHeight);
01015         conx = 0;
01016         cony = 0;
01017 }
01018 
01019 void glfPrint(char *s, int lenght)
01020 {
01021         int i;
01022 
01023         for (i=0; i<lenght; i++)
01024         {
01025                 if (s[i] > 31)
01026                 {
01027                         conData[cony*conWidth+conx] = s[i];
01028                         conx++;
01029                 } else
01030                 if (s[i] == '\n') conx = conWidth;
01031                 if (conx >= conWidth)
01032                 {
01033                         conx = 0;
01034                         cony++;
01035                         if (cony >= conHeight)
01036                         {
01037                                 /* Shift all console contents up */
01038                                 memcpy(conData, &conData[conWidth], conWidth*(conHeight-1));
01039                                 /* Fill bottom line by spaces */
01040                                 memset(&conData[conWidth*(conHeight-1)], 0, conWidth);
01041                                 cony = conHeight-1;
01042                         }
01043                 }
01044         }
01045 }
01046 
01047 void glfPrintString(char *s)
01048 {
01049         glfPrint(s, strlen(s));
01050 }
01051 
01052 void glfPrintChar(char s)
01053 {
01054         glfPrint(&s, 1);
01055 }
01056 
01057 void glfConsoleDraw()
01058 {
01059         int i, j;
01060         char s[512];
01061 
01062         for (i=0; i<conHeight; i++)
01063         {
01064                 memcpy(s, &conData[i*conWidth], conWidth);
01065                 s[conWidth] = 0;
01066                 if ((conCursor == GLF_YES) && (i == cony))
01067                 {
01068                         conCursorCount--;
01069                         if (conCursorCount < 0)
01070                         {
01071                                 conCursorCount = conCursorBlink;
01072                                 if (conCursorMode == GLF_YES) conCursorMode = GLF_NO;
01073                                 else conCursorMode = GLF_YES;
01074                         }
01075 
01076                         if (conCursorMode == GLF_YES)
01077                         for (j=0; j<conWidth; j++)
01078                         {
01079                                 if (!s[j])
01080                                 {
01081                                         s[j] = '_'; /* Draw cursor */
01082                                         s[j+1] = 0;
01083                                         break;
01084                                 }
01085                         }
01086                 }
01087                 glfDrawSolidStringF(conFont, s);
01088                 glTranslatef(0, -2, 0);
01089         }
01090 }
01091 
01092 void glfSetCursorBlinkRate(int Rate)
01093 {
01094         if (Rate > 0)
01095         {
01096                 conCursorBlink = Rate;
01097                 conCursorCount = Rate;
01098                 conCursorMode = GLF_YES;
01099         }
01100 }
01101 
01102 /* Set string centering for vector fonts */
01103 void glfStringCentering(GLboolean center)
01104 {
01105         m_string_center = center;
01106 }
01107 
01108 /* String direction for vector font (GLF_LEFT, GLF_RIGHT, GLF_UP, GLF_DOWN) */
01109 /* GLF_LEFT by default */
01110 void glfStringDirection(GLuint direction)
01111 {
01112         if (direction == GLF_LEFT || direction == GLF_RIGHT || 
01113                 direction == GLF_UP || direction == GLF_DOWN) m_direction = direction;
01114 }
01115 
01116 /* Get current text direction */
01117 GLuint glfGetStringDirection()
01118 {
01119         return m_direction;
01120 }
01121 
01122 
01123 /* Get string centering for vector fonts */
01124 GLboolean glfGetStringCentering()
01125 {
01126         return m_string_center;
01127 }
01128 
01129 /* Set rotate angle for vector fonts */
01130 void glfSetRotateAngle(float angle)
01131 {
01132         RotateAngle = angle;
01133 }
01134 
01135 
01136 /*
01137    --------------------------------------------------------------------------------- 
01138    ------------------------ Work with bitmapped fonts ------------------------------ 
01139    --------------------------------------------------------------------------------- 
01140 */
01141 
01142 
01143 /* Some color conversions */
01144 static void bwtorgba(unsigned char *b,unsigned char *l,int n)
01145 {
01146     while (n--)
01147     {
01148                 l[0] = *b; l[1] = *b;
01149                 l[2] = *b; l[3] = 0xff;
01150                 l += 4; b++;
01151     }
01152 }
01153 
01154 static void latorgba(unsigned char *b, unsigned char *a,unsigned char *l,int n)
01155 {
01156         while(n--)
01157         {
01158                 l[0] = *b; l[1] = *b;
01159                 l[2] = *b; l[3] = *a;
01160                 l += 4; b++; a++;
01161     }
01162 }
01163 
01164 static void rgbtorgba(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *l,int n)
01165 {
01166     while(n--)
01167         {
01168                 l[0] = r[0]; l[1] = g[0];
01169                 l[2] = b[0]; l[3] = 0xff;
01170                 l += 4; r++; g++; b++;
01171     }
01172 }
01173 
01174 static void rgbatorgba(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *a,unsigned char *l,int n)
01175 {
01176     while(n--)
01177         {
01178                 l[0] = r[0]; l[1] = g[0];
01179                 l[2] = b[0]; l[3] = a[0];
01180                 l += 4; r++; g++; b++; a++;
01181     }
01182 }
01183 
01184 typedef struct _ImageRec
01185 {
01186     unsigned short imagic;
01187     unsigned short type;
01188     unsigned short dim;
01189     unsigned short xsize, ysize, zsize;
01190     unsigned int min, max;
01191     unsigned int wasteBytes;
01192     char name[80];
01193     unsigned long colorMap;
01194     FILE *file;
01195     unsigned char *tmp, *tmpR, *tmpG, *tmpB;
01196     unsigned long rleEnd;
01197     unsigned int *rowStart;
01198     int *rowSize;
01199 } ImageRec;
01200 
01201 static void ConvertShort(unsigned short *array, long length)
01202 {
01203     unsigned b1, b2;
01204     unsigned char *ptr;
01205 
01206     ptr = (unsigned char *)array;
01207     while (length--) {
01208         b1 = *ptr++;
01209         b2 = *ptr++;
01210         *array++ = (b1 << 8) | (b2);
01211     }
01212 }
01213 
01214 static void ConvertLong(unsigned *array, long length)
01215 {
01216     unsigned b1, b2, b3, b4;
01217     unsigned char *ptr;
01218 
01219     ptr = (unsigned char *)array;
01220     while (length--)
01221         {
01222                 b1 = *ptr++;
01223                 b2 = *ptr++;
01224                 b3 = *ptr++;
01225                 b4 = *ptr++;
01226                 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
01227     }
01228 }
01229 
01230 /* Open RGB Image */
01231 static ImageRec *ImageOpen(FILE *f)
01232 {
01233     union
01234         {
01235                 int testWord;
01236                 char testByte[4];
01237     } endianTest;
01238 
01239     ImageRec *image;
01240     int swapFlag;
01241     int x;
01242 
01243     endianTest.testWord = 1;
01244     if (endianTest.testByte[0] == 1) swapFlag = 1;
01245         else swapFlag = 0;
01246 
01247     image = (ImageRec *)malloc(sizeof(ImageRec));
01248     if (image == NULL)
01249         {
01250                 fprintf(stderr, "Out of memory!\n");
01251                 exit(1);
01252     }
01253 
01254         image->file = f;
01255 
01256     fread(image, 1, 12, image->file);
01257 
01258     if (swapFlag) ConvertShort(&image->imagic, 6);
01259 
01260     image->tmp  = (unsigned char *)malloc(image->xsize*256);
01261     image->tmpR = (unsigned char *)malloc(image->xsize*256);
01262     image->tmpG = (unsigned char *)malloc(image->xsize*256);
01263     image->tmpB = (unsigned char *)malloc(image->xsize*256);
01264     if (image->tmp == NULL || image->tmpR == NULL || image->tmpG == NULL ||
01265         image->tmpB == NULL) 
01266         {
01267                 fprintf(stderr, "Out of memory!\n");
01268                 exit(1);
01269     }
01270 
01271     if ((image->type & 0xFF00) == 0x0100)
01272         {
01273                 x = image->ysize * image->zsize * sizeof(unsigned);
01274                 image->rowStart = (unsigned *)malloc(x);
01275                 image->rowSize = (int *)malloc(x);
01276                 if (image->rowStart == NULL || image->rowSize == NULL)
01277                 {
01278                     fprintf(stderr, "Out of memory!\n");
01279                     exit(1);
01280                 }
01281                 image->rleEnd = 512 + (2 * x);
01282                 fseek(image->file, 512+SEEK_SET_POS, SEEK_SET);
01283                 fread(image->rowStart, 1, x, image->file);
01284                 fread(image->rowSize, 1, x, image->file);
01285                 if (swapFlag)
01286                 {
01287                         ConvertLong(image->rowStart, x/(int)sizeof(unsigned));
01288                         ConvertLong((unsigned *)image->rowSize, x/(int)sizeof(int));
01289                 }
01290     }
01291         else
01292         {
01293                 image->rowStart = NULL;
01294                 image->rowSize = NULL;
01295     }
01296     return image;
01297 }
01298 
01299 /* Close Image and free data */
01300 static void ImageClose(ImageRec *image)
01301 {
01302         free(image->tmp);
01303         free(image->tmpR);
01304         free(image->tmpG);
01305         free(image->tmpB);
01306     free(image->rowSize);
01307     free(image->rowStart);
01308     free(image);
01309 }
01310 
01311 /* Pixels row decoding (if used RLE encoding) */
01312 static void ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z)
01313 {
01314     unsigned char *iPtr, *oPtr, pixel;
01315     int count;
01316 
01317     if ((image->type & 0xFF00) == 0x0100)
01318         {
01319                 fseek(image->file, (long)image->rowStart[y+z*image->ysize]+SEEK_SET_POS, SEEK_SET);
01320                 fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize], image->file);
01321 
01322                 iPtr = image->tmp;
01323                 oPtr = buf;
01324                 for (;;)
01325                 {
01326                         pixel = *iPtr++;
01327                     count = (int)(pixel & 0x7F);
01328                     if (!count) return;
01329                     if (pixel & 0x80) while (count--) *oPtr++ = *iPtr++;
01330                         else
01331                         {
01332                                 pixel = *iPtr++;
01333                                 while (count--) *oPtr++ = pixel;
01334                     }
01335                 }
01336     }
01337         else
01338         {
01339                 fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize)+SEEK_SET_POS, SEEK_SET);
01340                 fread(buf, 1, image->xsize, image->file);
01341     }
01342 }
01343 
01344 /* Read SGI (RGB) Image from file */
01345 static unsigned *read_texture(FILE *f, int *width, int *height, int *components)
01346 {
01347     unsigned *base, *lptr;
01348     unsigned char *rbuf, *gbuf, *bbuf, *abuf;
01349     ImageRec *image;
01350     int y;
01351 
01352     image = ImageOpen(f);
01353     
01354     if (!image) return NULL;
01355     (*width) = image->xsize;
01356     (*height) = image->ysize;
01357     (*components) = image->zsize;
01358     
01359         base = (unsigned *)malloc(image->xsize*image->ysize*sizeof(unsigned));
01360     rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
01361     gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
01362     bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
01363     abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
01364     
01365         if(!base || !rbuf || !gbuf || !bbuf) return NULL;
01366     lptr = base;
01367     for (y=0; y<image->ysize; y++)
01368         {
01369                 if(image->zsize >= 4)
01370                 {
01371                         ImageGetRow(image, rbuf, y, 0);
01372                         ImageGetRow(image, gbuf, y, 1);
01373                         ImageGetRow(image, bbuf, y, 2);
01374                         ImageGetRow(image, abuf, y, 3);
01375                         rgbatorgba(rbuf,gbuf,bbuf,abuf,(unsigned char *)lptr,image->xsize);
01376                         lptr += image->xsize;
01377                 }
01378                 else if(image->zsize == 3)
01379                 {
01380                         ImageGetRow(image,rbuf, y, 0);
01381                         ImageGetRow(image,gbuf, y, 1);
01382                         ImageGetRow(image,bbuf, y, 2);
01383                         rgbtorgba(rbuf,gbuf,bbuf,(unsigned char *)lptr,image->xsize);
01384                         lptr += image->xsize;
01385                 }
01386                 else if(image->zsize == 2)
01387                 {
01388                         ImageGetRow(image,rbuf, y, 0);
01389                         ImageGetRow(image,abuf, y, 1);
01390                         latorgba(rbuf,abuf,(unsigned char *)lptr,image->xsize);
01391                         lptr += image->xsize;
01392                 }
01393                 else
01394                 {
01395                         ImageGetRow(image, rbuf, y, 0);
01396                         bwtorgba(rbuf,(unsigned char *)lptr,image->xsize);
01397                         lptr += image->xsize;
01398                 }
01399     }
01400     ImageClose(image);
01401     free(rbuf);
01402     free(gbuf);
01403     free(bbuf);
01404     free(abuf);
01405 
01406     return (unsigned *) base;
01407 }
01408 
01409 /* Font texture conversion to mask texture */
01410 unsigned* texture_to_mask(unsigned* tex, int width, int height)
01411 {
01412         int nSize, i;
01413         unsigned *ret;
01414 
01415         nSize = width * height;
01416         ret = (unsigned *)malloc(nSize * sizeof(unsigned));
01417         for (i=0; i<nSize; i++) ret[i] = tex[i] & 0x00ffffff ? 0 : 0x00ffffff;
01418 
01419         return ret;
01420 }
01421 
01422 /* Load BMF file format, function return bitmap font descriptor */
01423 int glfLoadBMFFont(char *FName)
01424 {
01425         FILE *f;
01426         char Header[4];
01427         char FontName[97];
01428         int i, flag;
01429         int LEndian;
01430         float tx, ty, tw, th;
01431         unsigned char temp, *tp;
01432         unsigned *texture;      /* Texture image */
01433         unsigned *mask; /* Mask texture */
01434         int twidth, theight, tcomp;     /* Image parameters */
01435         float *temp_width;
01436 
01437         LEndian = LittleEndian();
01438 
01439         f = fopen(FName, "rb");
01440         if (f == NULL) return GLF_ERROR; /* Error opening file */
01441 
01442         /* Get header */
01443         fread(Header, 1, 3, f);
01444         Header[3] = 0;
01445         if (strcmp(Header, "BMF")) return GLF_ERROR; /* Not BMF format */
01446 
01447         /* Get font name */
01448         fread(FontName, 1, 96, f);
01449         FontName[96] = 0;
01450 
01451         /* Allocate space for temp widths */
01452         
01453         temp_width = (float *)malloc(sizeof(float)*256);
01454 
01455         /* Read all 256 symbols information */
01456         for (i=0; i<256; i++)
01457         {
01458                 fread(&tx, 4, 1, f);
01459                 fread(&ty, 4, 1, f);
01460                 fread(&tw, 4, 1, f);
01461                 fread(&th, 4, 1, f);
01462 
01463                 if (!LEndian)
01464                 {
01465                         tp = (unsigned char *)&tx;
01466                         temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
01467                         temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
01468                         tp = (unsigned char *)&ty;
01469                         temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
01470                         temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
01471                         tp = (unsigned char *)&tw;
01472                         temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
01473                         temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
01474                         tp = (unsigned char *)&th;
01475                         temp = tp[0]; tp[0] = tp[3]; tp[3] = temp;
01476                         temp = tp[1]; tp[1] = tp[2]; tp[2] = temp;
01477                 }
01478                 
01479                 Symbols[(int)i].x = tx;
01480                 Symbols[(int)i].y = ty;
01481                 Symbols[(int)i].width  = tw;
01482                 Symbols[(int)i].height = th;
01483                 temp_width[i] = tw;
01484         }
01485 
01486         /* Read texture image from file and build texture */
01487         texture = read_texture(f, &twidth, &theight, &tcomp);
01488         /* Generate mask texture */
01489         mask = texture_to_mask(texture, twidth, theight);
01490 
01491         /* Find unused font descriptor */
01492         flag = 0;
01493         for (i=0; i<MAX_FONTS; i++)
01494                 if (bmf_in_use[i] == 0)
01495                 {
01496                         /* Initialize this font */
01497                         bmf_in_use[i] = 1;
01498                         bmf_curfont = i;
01499                         flag = 1;
01500                         break;
01501                 }
01502         if (!flag) /* Not enought space for new texture */
01503         {
01504                 fclose(f);
01505                 free(texture);
01506                 free(mask);
01507                 free(temp_width);
01508                 return -1;
01509         }
01510 
01511         m_widths[bmf_curfont].width = temp_width;
01512 
01513         /* Generating textures for font and mask */
01514         glGenTextures(1, &bmf_texture[bmf_curfont]);
01515         glGenTextures(1, &bmf_mask[bmf_curfont]);
01516 
01517 
01518         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01519 
01520         /* Build font texture */
01521         glBindTexture(GL_TEXTURE_2D, bmf_texture[bmf_curfont]);
01522         glTexImage2D(GL_TEXTURE_2D, 0, 3, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
01523         
01524         /* Linear filtering for better quality */
01525         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01526         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01527         
01528         /* Build mask texture */
01529         glBindTexture(GL_TEXTURE_2D, bmf_mask[bmf_curfont]);
01530         glTexImage2D(GL_TEXTURE_2D, 0, 3, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, mask);
01531         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01532         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01533 
01534         free(texture);
01535         free(mask);
01536         fclose(f);
01537 
01538         /* Now build list for each symbol */
01539         list_base[bmf_curfont] = glGenLists(256);
01540         for (i=0; i<256; i++)
01541         {
01542                 glNewList(list_base[bmf_curfont]+i, GL_COMPILE);
01543                 
01544                 glBegin(GL_QUADS);
01545                         glTexCoord2f(Symbols[(int)i].x, Symbols[(int)i].y); glVertex2f(0, 0);
01546                         glTexCoord2f(Symbols[(int)i].x+Symbols[(int)i].width, Symbols[(int)i].y); glVertex2f(Symbols[(int)i].width, 0);
01547                         glTexCoord2f(Symbols[(int)i].x+Symbols[(int)i].width, Symbols[(int)i].y+Symbols[(int)i].height); glVertex2f(Symbols[(int)i].width, Symbols[(int)i].height);
01548                         glTexCoord2f(Symbols[(int)i].x, Symbols[(int)i].y+Symbols[(int)i].height); glVertex2f(0, Symbols[(int)i].height);
01549                 glEnd();
01550                 glTranslatef(Symbols[(int)i].width+sym_space, 0, 0);
01551 
01552                 glEndList();
01553                 if (Symbols[(int)i].height > m_max_height[bmf_curfont]) m_max_height[bmf_curfont] = Symbols[(int)i].height;
01554         }
01555         return bmf_curfont;
01556 }
01557 
01558 /* Unloads bitmap font by descriptor */
01559 int glfUnloadBMFFontD(int bmf_descriptor)
01560 {
01561         if ((bmf_descriptor < 0) || (bmf_in_use[bmf_descriptor] == 0)) return GLF_ERROR;
01562 
01563         bmf_in_use[bmf_descriptor] = 0;
01564 
01565         glDeleteTextures(1, &bmf_texture[bmf_descriptor]);
01566         glDeleteTextures(1, &bmf_mask[bmf_descriptor]);
01567 
01568         if (bmf_descriptor == bmf_curfont) bmf_curfont = -1;
01569 
01570         return GLF_OK;
01571 }
01572 
01573 /* Unloads current bitmap font */
01574 int glfUnloadBMFFont()
01575 {
01576         return glfUnloadBMFFontD(bmf_curfont);
01577 }
01578 
01579 /* Start bitmap drawing function */
01580 void glfStartBitmapDrawing()
01581 {
01582         /* Enable 2D Texturing */
01583         glGetBooleanv(GL_TEXTURE_2D, &bmf_texturing);
01584         glEnable(GL_TEXTURE_2D);
01585 
01586         glBindTexture(GL_TEXTURE_2D, bmf_texture[bmf_curfont]);
01587 }
01588 
01589 /* Stop bitmap drawing function */
01590 void glfStopBitmapDrawing()
01591 {
01592         /* Return previuos state of texturing */
01593         if (bmf_texturing) glEnable(GL_TEXTURE_2D);
01594         else glDisable(GL_TEXTURE_2D);
01595 }
01596 
01597 /* Select current BMF font */
01598 int glfSetCurrentBMFFont(int Font_Descriptor)
01599 {
01600         if ((Font_Descriptor < 0) || (bmf_in_use[Font_Descriptor] == 0)) return GLF_ERROR;
01601 
01602         bmf_curfont = Font_Descriptor;
01603         return GLF_OK;
01604 }
01605 
01606 /* Get current BMF font */
01607 int glfGetCurrentBMFFont()
01608 {
01609         return bmf_curfont;
01610 }
01611 
01612 /* Draw one bitmapped symbol by current font */
01613 void glfDrawBSymbol(char s)
01614 {
01615         if ((bmf_curfont < 0) || (bmf_in_use[bmf_curfont] == 0)) return;
01616         
01617         glCallList(list_base[bmf_curfont]+(unsigned char)s);
01618 }
01619 
01620 /* Draw bitmapped string */
01621 void glfDrawBString(char *s)
01622 {
01623         GLfloat temp_trans;
01624         int i;
01625 
01626         temp_trans = 0;
01627 
01628         if ((bmf_curfont < 0) || (bmf_in_use[bmf_curfont] == 0)) return;
01629 
01630         /* Calculate length of all string */
01631         for (i=0; i<(int)strlen(s); i++)
01632                 temp_trans += m_widths[bmf_curfont].width[s[i]] + sym_space;
01633         
01634         glListBase(list_base[bmf_curfont]);
01635         if (m_bitmap_string_center == GL_TRUE)
01636         {
01637                 glPushMatrix();
01638                 glTranslatef(-temp_trans/2, 0, 0);
01639         }
01640         glCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s);
01641         if (m_bitmap_string_center == GL_TRUE)  glPopMatrix();
01642 }
01643 
01644 void glfDrawBMaskSymbol(char s)
01645 {
01646         if ((bmf_curfont < 0) || (bmf_in_use[bmf_curfont] == 0)) return;
01647         
01648         glPushMatrix();
01649         glPushAttrib(GL_CURRENT_BIT);
01650         
01651         /* Draw the text as a mask in black */
01652         glColor3ub(0xff, 0xff, 0xff);
01653         glBlendFunc(GL_DST_COLOR, GL_ZERO);
01654         glBindTexture(GL_TEXTURE_2D, bmf_mask[bmf_curfont]);
01655 
01656         glCallList(list_base[bmf_curfont]+(unsigned char)s);
01657 
01658         glPopAttrib();
01659         glPopMatrix();
01660         
01661         glBindTexture(GL_TEXTURE_2D, bmf_texture[bmf_curfont]);
01662         
01663         /* Now draw the text over only the black bits in the requested color */
01664         glBlendFunc(GL_ONE, GL_ONE);
01665 
01666         glCallList(list_base[bmf_curfont]+(unsigned char)s);
01667 }
01668 
01669 void glfDrawBMaskString(char *s)
01670 {
01671         GLfloat temp_trans;
01672         int i;
01673 
01674         temp_trans = 0;
01675 
01676         if ((bmf_curfont < 0) || (bmf_in_use[bmf_curfont] == 0)) return;
01677 
01678         /* Calculate length of all string */
01679         for (i=0; i<(int)strlen(s); i++)
01680                 temp_trans += m_widths[bmf_curfont].width[s[i]] + sym_space;
01681 
01682         glPushMatrix();
01683         glPushAttrib(GL_CURRENT_BIT);
01684         
01685         /* Draw the text as a mask in black */
01686         glColor3ub(0xff, 0xff, 0xff);
01687         glBlendFunc(GL_DST_COLOR, GL_ZERO);
01688         glBindTexture(GL_TEXTURE_2D, bmf_mask[bmf_curfont]);
01689 
01690         glListBase(list_base[bmf_curfont]);
01691         if (m_bitmap_string_center == GL_TRUE)
01692         {
01693                 glPushMatrix();
01694                 glTranslatef(-temp_trans/2, 0, 0);
01695         }
01696         glCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s);
01697         if (m_bitmap_string_center == GL_TRUE)  glPopMatrix();
01698 
01699         glPopAttrib();
01700         glPopMatrix();
01701 
01702         glBindTexture(GL_TEXTURE_2D, bmf_texture[bmf_curfont]);
01703         
01704         /* Now draw the text over only the black bits in the requested color */
01705         glBlendFunc(GL_ONE, GL_ONE);
01706         glListBase(list_base[bmf_curfont]);
01707         if (m_bitmap_string_center == GL_TRUE)
01708         {
01709                 glPushMatrix();
01710                 glTranslatef(-temp_trans/2, 0, 0);
01711         }
01712         glCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s);
01713         if (m_bitmap_string_center == GL_TRUE)  glPopMatrix();
01714 }
01715 
01716 /* Set string centering for bitmap fonts */
01717 void glfBitmapStringCentering(GLboolean center)
01718 {
01719         m_bitmap_string_center = center;
01720 }
01721 
01722 /* Set string centering for bitmap fonts */
01723 GLboolean glfBitmapGetStringCentering()
01724 {
01725         return m_bitmap_string_center;
01726 }
01727 
01728 /* Set rotate angle for bitmap fonts */
01729 void glfSetBRotateAngle(float angle)
01730 {
01731         RotateAngleB = angle;
01732 }

Generated on Mon Feb 15 11:06:46 2010 for loon by  doxygen 1.3.9.1