home *** CD-ROM | disk | FTP | other *** search
/ Enter 2005 March / ENTER.ISO / files / fwp-0.0.6-win32-installer.exe / texfont.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-12-19  |  14.3 KB  |  467 lines

  1. /*!
  2. \file texfont.cpp
  3. \author Karsten Schwenk
  4.  
  5. See header for description (font.h).
  6. */
  7.  
  8. #include "texfont.h"
  9.  
  10. #include "Tokenizer.h"
  11. #include "TextureHandler.h"
  12. #include "File.h"
  13.  
  14. //#include <stdio.h>
  15. //#include <stdlib.h>
  16. #ifndef WIN32
  17. #include <ctype.h>    // fr isdigit
  18. #include <stdarg.h>    // fr linux va_kram
  19. #define _vsnprintf vsnprintf
  20. #endif
  21.  
  22. #include "SDL.h"
  23.  
  24.  
  25. //! The font colors that can be accessed via '^0-9' (see #setFontColor() and detailed description of font.h)
  26. static float fontColors[10][4]={
  27.     {0.0f, 0.0f, 0.0f, 1.0f},
  28.     {1.0f, 1.0f, 1.0f, 1.0f},
  29.     {1.0f, 0.0f, 0.0f, 1.0f},
  30.     {0.0f, 1.0f, 0.0f, 1.0f},
  31.     {0.0f, 0.0f, 1.0f, 1.0f},
  32.     {1.0f, 1.0f, 0.0f, 1.0f},
  33.     {0.0f, 1.0f, 1.0f, 1.0f},
  34.     {1.0f, 0.0f, 1.0f, 1.0f},
  35.     {0.75f, 0.75f, 0.75f, 1.0f},
  36.     {0.5f, 0.5f, 0.5f, 1.0f},
  37. };
  38.  
  39.  
  40.  
  41. /*!
  42. This function loads a texFont into a #texFont_s struct and returns a pointer to it.
  43. When the font is no longer needed it can be freed using #freeFont(). The file must be a .font file, see font.h for details.
  44. \c NULL is returned on errors.
  45. \warning In most situations you should use #FontHandler::getFont() to get pointers to fonts.
  46.         This prevents multiple loading of the same font.
  47. \param filename name of the .font-file that describes this font
  48. \return a pointer to the loaded texFont (or \c NULL)
  49. */
  50. texFont_t* loadFont(const char* filename){
  51.     char buff[256];
  52.     Tokenizer t(" \"\t\n\r", "\"");
  53.  
  54.     File* f = new File(filename, "rt");
  55.     if(!f->isOpen()){
  56.         return NULL;
  57.     }
  58.  
  59.     texFont_t* ret=new texFont_t;
  60.  
  61.     ret->filename=newString(filename);
  62.     ret->spacing=0;
  63.     ret->height=0;
  64.     ret->tex=NULL;
  65.     ret->texCoordHeight=0.0;
  66.     for(int i=0;i<TEX_FONT_MAX_CHARACTERS;i++)
  67.         ret->chars[i]=NULL;
  68.  
  69.     while(f->readLine(256, buff, true) != -1){
  70. //                printf("AH!\n");
  71.  
  72.         t.tokenize(buff);
  73.         if(t.tokc < 2)
  74.             continue;
  75.  
  76.         if(streq(t.tokv[0], "texture")){
  77.             ret->tex=TextureHandler::getTexture(t.tokv[1]);
  78.         }else if(streq(t.tokv[0], "height")){
  79.             ret->height=atoi(t.tokv[1]);
  80.             ret->texCoordHeight=ret->height/(float)ret->tex->height;
  81.         }else if(streq(t.tokv[0], "spacing")){
  82.             ret->spacing=atoi(t.tokv[1]);
  83.         }else if(streq(t.tokv[0], "character") && t.tokc == 5){
  84.             if(*t.tokv[1]>0 && *t.tokv[1]<TEX_FONT_MAX_CHARACTERS){
  85.                 int c = *t.tokv[1];
  86.                 if(c=='\'' && strlen(t.tokv[1])>=2 && t.tokv[1][1]=='\''){    // double ' means "
  87.                     c='\"';//t.tokv[1][1];
  88.                 }
  89. //                printf("char: %c, %i\n", c, c);
  90.                 ret->chars[c]=new texFontCharacter_t;
  91.                 ret->chars[c]->u=atoi(t.tokv[2])/(float)ret->tex->width;
  92.                 ret->chars[c]->v=atoi(t.tokv[3])/(float)ret->tex->height;
  93.                 ret->chars[c]->width=atoi(t.tokv[4]);
  94.                 ret->chars[c]->texCoordWidth=ret->chars[c]->width/(float)ret->tex->width;
  95.             }
  96.         }
  97.     }
  98.     
  99.     return ret;
  100. }
  101.  
  102. /*!
  103. This function frees a #texFont_s struct allocated by #loadFont().
  104. \warning In most situations you should use the #FontHandler to manage pointers to fonts.
  105. \param font a pointer to the loaded texFont
  106. */
  107. void freeFont(texFont_t* font){
  108.     if(font!=NULL){
  109.         for(int i=0;i<TEX_FONT_MAX_CHARACTERS;i++){
  110.             if(font->chars[i]!=NULL)
  111.                 delete font->chars[i];
  112.         }
  113.         if(font->tex!=NULL)
  114.             TextureHandler::releaseTexture(font->tex);
  115.  
  116.         if(font->filename!=NULL)
  117.             delete[] font->filename;
  118.  
  119.         delete font;
  120.     }
  121. }
  122.  
  123. /*!
  124. This function returns how many pixels \c string is wide in font \c font (\b including the fonts spacing). This is used mainly in the \c drawAlignedString-functions to calculate the correct x-offset.
  125. \param font a pointer a #texFont_s struct
  126. \param string a NULL-terminated string whoose width should be calculated
  127. \return width of the string in pixels
  128. \bug color coding chars are not counted correctly -> wrong width
  129. */
  130. int getStringWidth(texFont_t* font, const char* string){
  131.     if(font==NULL || string==NULL)
  132.         return 0;
  133.  
  134.     char* p=(char*)string;
  135.     int cx=0;
  136.  
  137.     while(*p!='\0'){
  138.         if( *p=='^' && isdigit((int)(*(p+1))) ){    // don't count color coding chars
  139.             p+=2;
  140.             continue;
  141.         }
  142.         if(    *p<0 || font->chars[*p]==NULL){    // count as height/2 - oder doch nicht?
  143.             //cx = (int)( cx + font->height*0.5 + font->spacing );
  144.             p++;
  145.             continue;
  146.         }
  147.  
  148.         cx = cx + font->chars[*p]->width + font->spacing;
  149.         p++;
  150.     }
  151.     return cx-font->spacing;        // sub spacing after last character again
  152. }
  153.  
  154. /*!
  155. This function sets the OpenGl color according to the values in #fontColors. This is used to change color in a string dynamicaly. See file describtion of font.h for details.
  156. \param c digit-character to reference the #fontColors array
  157. \return \c true if a new color was set, \c false if not (illegal character)
  158. */
  159. bool setFontColor(char c){
  160.     if(c=='0')
  161.         glColor4fv(fontColors[0]);
  162.     else if(c=='1')
  163.         glColor4fv(fontColors[1]);
  164.     else if(c=='2')
  165.         glColor4fv(fontColors[2]);
  166.     else if(c=='3')
  167.         glColor4fv(fontColors[3]);
  168.     else if(c=='4')
  169.         glColor4fv(fontColors[4]);
  170.     else if(c=='5')
  171.         glColor4fv(fontColors[5]);
  172.     else if(c=='6')
  173.         glColor4fv(fontColors[6]);
  174.     else if(c=='7')
  175.         glColor4fv(fontColors[7]);
  176.     else if(c=='8')
  177.         glColor4fv(fontColors[8]);
  178.     else if(c=='9')
  179.         glColor4fv(fontColors[9]);
  180.     else if(c=='b'){
  181.         if((SDL_GetTicks()/700)%2)
  182.             glColor4fv(fontColors[0]);// black
  183.         else
  184.             glColor4fv(fontColors[2]);// red
  185.     }else
  186.         return false;
  187.  
  188.     return true;
  189. }
  190.  
  191. /*!
  192. This function draws string \c string on he screen at \c (x,y) using font \c font. Other functions have additional arguments for alignment, scaling, etc. and take format strings instead of 'normal' strings - but they are used in exactly the same manner, so I don't think it is neccassary to document them.
  193.  
  194. The string is printed with the currently set OpenGL color (unless not changed by '^0-9'). \c GL_BLEND must be enabled, \c GL_TEXTURE_2D is disabled best (because your texture binding will change!).
  195. \param x x screen coordinate where string should be drawed
  196. \param y y screen coordinate where string should be drawed
  197. \param font font that should be used
  198. \param string string that should be drawed
  199. */
  200. void drawString(int x, int y, texFont_t* font, const char* string){
  201.     if(font==NULL || string==NULL)
  202.         return;
  203.  
  204.     char* p=(char*)string;
  205.     int cx=x;
  206.  
  207.     glEnable(GL_TEXTURE_2D);
  208.     glBindTexture(GL_TEXTURE_2D, font->tex->texName);
  209.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  210.  
  211.     glBegin(GL_QUADS);
  212.     while(*p!='\0'){
  213.         if(*p<0 || font->chars[*p]==NULL){
  214.             p++;
  215.             continue;
  216.         }
  217.  
  218.         if(*p=='^' && setFontColor(*(p+1))){
  219.                 p+=2;
  220.                 continue;
  221.         }
  222. //        printf("char: %c | cx: %i | wi:%i | sp:%i\n", *p, cx,font->chars[*p]->width, font->spacing);
  223.         // character
  224.         glTexCoord2f(font->chars[*p]->u, font->chars[*p]->v);    // lower left
  225.         glVertex2i(cx, y);
  226.         glTexCoord2f(font->chars[*p]->u+font->chars[*p]->texCoordWidth, font->chars[*p]->v);    // lower right
  227.         glVertex2i(cx+font->chars[*p]->width, y);
  228.         glTexCoord2f(font->chars[*p]->u+font->chars[*p]->texCoordWidth, font->chars[*p]->v+font->texCoordHeight);    // upper right
  229.         glVertex2i(cx+font->chars[*p]->width, y+font->height);
  230.         glTexCoord2f(font->chars[*p]->u, font->chars[*p]->v+font->texCoordHeight);    //upper left
  231.         glVertex2i(cx, y+font->height);
  232.  
  233.         cx = cx + font->chars[*p]->width + font->spacing;
  234.         p++;
  235.     }
  236.     glEnd();
  237.  
  238.     glDisable(GL_TEXTURE_2D);
  239.     
  240. }
  241.  
  242. void drawScaledString(int x, int y, float scaleX, float scaleY, texFont_t* font, const char* string){
  243.     if(font==NULL || string==NULL)
  244.         return;
  245.  
  246.     char* p=(char*)string;
  247.     float cx=(float)(x);
  248.  
  249.     glEnable(GL_TEXTURE_2D);
  250.     glBindTexture(GL_TEXTURE_2D, font->tex->texName);
  251.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  252.  
  253.     glBegin(GL_QUADS);
  254.     while(*p!='\0'){
  255.         if(*p<0 || font->chars[*p]==NULL){
  256.             p++;
  257.             continue;
  258.         }
  259.  
  260.         if(*p=='^' && setFontColor(*(p+1))){
  261.                 p+=2;
  262.                 continue;
  263.         }
  264. //        printf("char: %c | cx: %i | wi:%i | sp:%i\n", *p, cx,font->chars[*p]->width, font->spacing);
  265.         // character
  266.         glTexCoord2f(font->chars[*p]->u, font->chars[*p]->v);    // lower left
  267.         glVertex2f(cx, (float)y);
  268.         glTexCoord2f(font->chars[*p]->u+font->chars[*p]->texCoordWidth, font->chars[*p]->v);    // lower right
  269.         glVertex2f(cx+font->chars[*p]->width*scaleX, (float)y);
  270.         glTexCoord2f(font->chars[*p]->u+font->chars[*p]->texCoordWidth, font->chars[*p]->v+font->texCoordHeight);    // upper right
  271.         glVertex2f(cx+font->chars[*p]->width*scaleX, y+font->height*scaleY);
  272.         glTexCoord2f(font->chars[*p]->u, font->chars[*p]->v+font->texCoordHeight);    //upper left
  273.         glVertex2f(cx, y+font->height*scaleY);
  274.  
  275.         cx = cx + (font->chars[*p]->width + font->spacing)*scaleX;
  276.         p++;
  277.     }
  278.     glEnd();
  279.  
  280.     glDisable(GL_TEXTURE_2D);
  281. }
  282.  
  283. void drawAlignedString(int x, int y, texFont_t* font, int alignment, const char* string){
  284.     if(font==NULL || string==NULL)
  285.         return;
  286.  
  287.     char* p=(char*)string;
  288.     int cx;
  289.  
  290. //    printf("stringWidth;: %i\n", getStringWidth(font, string));
  291.     if(alignment==TEXT_ALIGN_RIGHT)
  292.         cx=x-getStringWidth(font, string);
  293.     else if(alignment==TEXT_ALIGN_CENTER)
  294.         cx=x-getStringWidth(font, string)/2;
  295.     else
  296.         cx=x;
  297.  
  298.     glEnable(GL_TEXTURE_2D);
  299.     glBindTexture(GL_TEXTURE_2D, font->tex->texName);
  300.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  301.  
  302.     glBegin(GL_QUADS);
  303.     while(*p!='\0'){
  304.         if(*p<0 || font->chars[*p]==NULL){
  305.             p++;
  306.             continue;
  307.         }
  308.  
  309.         if(*p=='^' && setFontColor(*(p+1))){
  310.                 p+=2;
  311.                 continue;
  312.         }
  313. //        printf("char: %c | cx: %i | wi:%i | sp:%i\n", *p, cx,font->chars[*p]->width, font->spacing);
  314.         // character
  315.         glTexCoord2f(font->chars[*p]->u, font->chars[*p]->v);    // lower left
  316.         glVertex2i(cx, y);
  317.         glTexCoord2f(font->chars[*p]->u+font->chars[*p]->texCoordWidth, font->chars[*p]->v);    // lower right
  318.         glVertex2i(cx+font->chars[*p]->width, y);
  319.         glTexCoord2f(font->chars[*p]->u+font->chars[*p]->texCoordWidth, font->chars[*p]->v+font->texCoordHeight);    // upper right
  320.         glVertex2i(cx+font->chars[*p]->width, y+font->height);
  321.         glTexCoord2f(font->chars[*p]->u, font->chars[*p]->v+font->texCoordHeight);    //upper left
  322.         glVertex2i(cx, y+font->height);
  323.  
  324.         cx = cx + font->chars[*p]->width + font->spacing;
  325.         p++;
  326.     }
  327.     glEnd();
  328.  
  329.     glDisable(GL_TEXTURE_2D);
  330. }
  331.  
  332. void drawScaledAndAlignedString(int x, int y, float scaleX, float scaleY, texFont_t* font, int alignment, const char* string){
  333.     if(font==NULL || string==NULL)
  334.         return;
  335.  
  336.     char* p=(char*)string;
  337.     float cx;
  338.  
  339. //    printf("stringWidth;: %i\n", getStringWidth(font, string));
  340.     if(alignment==TEXT_ALIGN_RIGHT)
  341.         cx=x-(getStringWidth(font, string)*scaleX);
  342.     else if(alignment==TEXT_ALIGN_CENTER)
  343.         cx=x-(getStringWidth(font, string)*scaleX)/2;
  344.     else
  345.         cx=(float)x;
  346.  
  347.     glEnable(GL_TEXTURE_2D);
  348.     glBindTexture(GL_TEXTURE_2D, font->tex->texName);
  349.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  350.  
  351.     glBegin(GL_QUADS);
  352.     while(*p!='\0'){
  353.         if(*p<0 || font->chars[*p]==NULL){    // THINKABOUTME: alle chars mit ascii>128 ignorieren? oder X ausgeben?
  354.             //glDisable(GL_TEXTURE_2D);
  355.             //glBegin(GL_LINE_LOOP);
  356.             //    glVertex2f(cx, (float)y);
  357.             //    glVertex2f(cx+font->height*0.5f*scaleX, (float)y);
  358.             //    glVertex2f(cx+font->height*0.5f*scaleX, y+font->height*scaleY);
  359.             //    glVertex2f(cx, y+font->height*scaleY);
  360.             //glEnd();
  361.             //glEnable(GL_TEXTURE_2D);
  362.             //glBindTexture(GL_TEXTURE_2D, font->tex->texName);
  363.             //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  364.  
  365.             //cx = cx + (font->height*0.5f + font->spacing)*scaleX;
  366.             p++;
  367.             continue;
  368.         }
  369.  
  370.         if(*p=='^' && setFontColor(*(p+1))){
  371.             p+=2;
  372.             continue;
  373.         }
  374.  
  375. //        printf("char: %c | cx: %i | wi:%i | sp:%i\n", *p, cx,font->chars[*p]->width, font->spacing);
  376.         // character
  377.         glTexCoord2f(font->chars[*p]->u, font->chars[*p]->v);    // lower left
  378.         glVertex2f(cx, (float)y);
  379.         glTexCoord2f(font->chars[*p]->u+font->chars[*p]->texCoordWidth, font->chars[*p]->v);    // lower right
  380.         glVertex2f(cx+font->chars[*p]->width*scaleX, (float)y);
  381.         glTexCoord2f(font->chars[*p]->u+font->chars[*p]->texCoordWidth, font->chars[*p]->v+font->texCoordHeight);    // upper right
  382.         glVertex2f(cx+font->chars[*p]->width*scaleX, y+font->height*scaleY);
  383.         glTexCoord2f(font->chars[*p]->u, font->chars[*p]->v+font->texCoordHeight);    //upper left
  384.         glVertex2f(cx, y+font->height*scaleY);
  385.  
  386.         cx = cx + (font->chars[*p]->width + font->spacing)*scaleX;
  387.         p++;
  388.     }
  389.     glEnd();
  390.  
  391.     glDisable(GL_TEXTURE_2D);
  392. }
  393.  
  394. void drawShadowedString(
  395.     float x, float y, float scale, int shadowOffset, texFont_t* font, int alignment, const char* string){
  396.  
  397.     float oldColor[4];
  398.     glGetFloatv(GL_CURRENT_COLOR, oldColor);
  399.  
  400.     glColor4f(0.0f, 0.0f, 0.0f, 0.7f);
  401.     drawScaledAndAlignedString((int)((x+shadowOffset)), (int)((y-shadowOffset))
  402.         , scale, scale, font, alignment, string);
  403.  
  404.     glColor4fv(oldColor);
  405.     drawScaledAndAlignedString((int)(x), (int)(y)
  406.         , scale, scale, font, alignment, string);
  407.  
  408. }
  409.  
  410.  
  411.  
  412. void drawFormatString(int x, int y, texFont_t* font, const char* formatString, ...){
  413.     va_list ap;
  414.     char toStringBuffer[512];
  415.  
  416.     va_start (ap, formatString);
  417.     _vsnprintf(toStringBuffer, 511, formatString, ap);
  418.     va_end(ap);
  419.     toStringBuffer[511]='\0';
  420.     drawString(x,y,font,toStringBuffer);
  421. }
  422. void drawScaledFormatString(int x, int y, float scaleX, float scaleY, texFont_t* font, const char* formatString, ...){
  423.     va_list ap;
  424.     char toStringBuffer[512];
  425.  
  426.     va_start (ap, formatString);
  427.     _vsnprintf(toStringBuffer, 511, formatString, ap);
  428.     va_end(ap);
  429.     toStringBuffer[511]='\0';
  430.     drawScaledString(x,y,scaleX, scaleY, font,toStringBuffer);
  431. }
  432. void drawAlignedFormatString(int x, int y, texFont_t* font, int alignment, const char* formatString, ...){
  433.     va_list ap;
  434.     char toStringBuffer[512];
  435.  
  436.     va_start (ap, formatString);
  437.     _vsnprintf(toStringBuffer, 511, formatString, ap);
  438.     va_end(ap);
  439.     toStringBuffer[511]='\0';
  440.     drawAlignedString(x,y,font,alignment,toStringBuffer);
  441. }
  442. void drawScaledAndAlignedFormatString(int x, int y, float scaleX, float scaleY, texFont_t* font, int alignment, const char* formatString, ...){
  443.     va_list ap;
  444.     char toStringBuffer[512];
  445.  
  446.     va_start (ap, formatString);
  447.     _vsnprintf(toStringBuffer, 511, formatString, ap);
  448.     va_end(ap);
  449.     toStringBuffer[511]='\0';
  450.     drawScaledAndAlignedString(x,y,scaleX, scaleY, font,alignment,toStringBuffer);
  451. }
  452.  
  453. void drawShadowedFormatString(
  454.     float x, float y, float scale, int shadowOffset, texFont_t* font, int alignment, const char* formatString, ...){
  455.  
  456.     va_list ap;
  457.     char toStringBuffer[512];
  458.  
  459.     va_start (ap, formatString);
  460.     _vsnprintf(toStringBuffer, 511, formatString, ap);
  461.     va_end(ap);
  462.     toStringBuffer[511]='\0';
  463.     drawShadowedString(x, y ,scale,shadowOffset, font, alignment, toStringBuffer);
  464.  
  465. }
  466.  
  467.