home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / rendertext.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-04  |  6.5 KB  |  239 lines

  1. // rendertext.cpp: font rendering
  2.  
  3. #include "cube.h"
  4.  
  5. struct font
  6. {
  7.     struct charinfo
  8.     {
  9.         short x, y, w, h;
  10.     };
  11.  
  12.     char *name;
  13.     Texture *tex;
  14.     vector<charinfo> chars;
  15.     short defaultw, defaulth;
  16.     short offsetx, offsety, offsetw, offseth;
  17. };
  18.  
  19. static hashtable<char *, font> fonts;
  20. static font *fontdef = NULL, *curfont = NULL;
  21.  
  22. void newfont(char *name, char *tex, char *defaultw, char *defaulth, char *offsetx, char *offsety, char *offsetw, char *offseth)
  23. {
  24.     font *f = fonts.access(name);
  25.     if(!f)
  26.     {
  27.         name = newstring(name);
  28.         f = &fonts[name];
  29.         f->name = name;
  30.     }
  31.  
  32.     f->tex = textureload(tex);
  33.     f->chars.setsize(0);
  34.     f->defaultw = ATOI(defaultw);
  35.     f->defaulth = ATOI(defaulth);
  36.     f->offsetx = ATOI(offsetx);
  37.     f->offsety = ATOI(offsety);
  38.     f->offsetw = ATOI(offsetw);
  39.     f->offseth = ATOI(offseth);
  40.  
  41.     fontdef = f;
  42. }
  43.  
  44. void fontchar(int x, int y, int w, int h)
  45. {
  46.     if(!fontdef) return;
  47.  
  48.     font::charinfo &c = fontdef->chars.add();
  49.     c.x = x;
  50.     c.y = y;
  51.     c.w = w ? w : fontdef->defaultw;
  52.     c.h = h ? h : fontdef->defaulth;
  53. }
  54.  
  55. COMMANDN(font, newfont, ARG_8STR);
  56. COMMANDN(fontchar, fontchar, ARG_4INT);
  57.  
  58. bool setfont(char *name)
  59. {
  60.     font *f = fonts.access(name);
  61.     if(!f) return false;
  62.     curfont = f;
  63.     return true;
  64. }
  65.  
  66. int char_width(int c, int x)
  67. {
  68.     if(!curfont) return x;
  69.     else if(c=='\t') x = (x+PIXELTAB)/PIXELTAB*PIXELTAB;
  70.     else if(c==' ') x += curfont->defaultw;
  71.     else if(curfont->chars.inrange(c-33))
  72.     {
  73.         c -= 33;
  74.         x += curfont->chars[c].w + 1;
  75.     }
  76.     return x;
  77. }
  78.  
  79. static vector<int> *columns = NULL;
  80.  
  81. void text_startcolumns()
  82. {
  83.     if(!columns) columns = new vector<int>;
  84. }
  85.  
  86. void text_endcolumns()
  87. {
  88.     DELETEP(columns);
  89. }
  90.  
  91. int text_width(const char *str, int limit)
  92. {
  93.     int x = 0, col = 0;
  94.     for(int i = 0; str[i] && (limit<0 || i<limit); i++)
  95.     {
  96.         switch(str[i])
  97.         {
  98.             case '\f':
  99.                 i++;
  100.                 break;
  101.  
  102.             case '\t':
  103.                 x = char_width('\t', x);
  104.                 if(columns)
  105.                 {
  106.                     while(col>=columns->length()) columns->add(0);
  107.                     x = max(x, (*columns)[col]);
  108.                     (*columns)[col] = x;
  109.                     col++;
  110.                 }
  111.                 break;
  112.  
  113.             default:
  114.                 x = char_width(str[i], x);
  115.                 break;
  116.         }
  117.     }
  118.     return x;
  119. }
  120.  
  121. int text_visible(const char *str, int max)
  122. {
  123.     int i = 0, x = 0;
  124.     while(str[i])
  125.     {
  126.         if(str[i]=='\f')
  127.         {
  128.             i += 2;
  129.             continue;
  130.         }
  131.         x = char_width(str[i], x);
  132.         if(x > max) return i;
  133.         ++i;
  134.     }
  135.     return i;
  136. }
  137.  
  138. // cut strings to fit on screen
  139. void text_block(const char *str, int max, vector<char *> &lines)
  140. {
  141.     if(!str) return;
  142.     int visible;
  143.     while((visible = text_visible(str, max)))
  144.     {
  145.         const char *newline = (const char *)memchr(str, '\n', visible);
  146.         if(newline) visible = newline+1-str;
  147.         else if(str[visible]) // wrap words
  148.         {
  149.             int v = visible;
  150.             while(v > 0 && str[v] != ' ') v--;
  151.             if(v) visible = v+1;
  152.         }
  153.         char *t = lines.add(newstring((size_t)visible));
  154.         s_strncpy(t, str, visible+1);
  155.         str += visible;
  156.     }
  157. }
  158.  
  159. void draw_textf(const char *fstr, int left, int top, ...)
  160. {
  161.     s_sprintfdlv(str, top, fstr);
  162.     draw_text(str, left, top);
  163. }
  164.  
  165. void draw_text(const char *str, int left, int top)
  166. {
  167.     if(!curfont) return;
  168.  
  169.     glBlendFunc(GL_ONE, GL_ONE);
  170.     glBindTexture(GL_TEXTURE_2D, curfont->tex->id);
  171.     glColor3ub(255, 255, 255);
  172.  
  173.     static float colorstack[8][4];
  174.     int colorpos = 0, x = left, y = top, col = 0;
  175.  
  176.     glBegin(GL_QUADS);
  177.     for(int i = 0; str[i]; i++)
  178.     {
  179.         int c = str[i];
  180.         switch(c)
  181.         {
  182.             case '\t':
  183.                 if(columns && col<columns->length()) x = left + (*columns)[col++];
  184.                 else x = (x-left+PIXELTAB)/PIXELTAB*PIXELTAB+left; 
  185.                 continue;
  186.  
  187.             case '\f':
  188.                 switch(str[i+1])
  189.                 {
  190.                     case '0': glColor3ub(64,  255, 128); i++; continue;   // green: player talk
  191.                     case '1': glColor3ub(96,  160, 255); i++; continue;   // blue: team chat
  192.                     case '2': glColor3ub(255, 192, 64);  i++; continue;   // yellow: gameplay action messages, only actions done by players
  193.                     case '3': glColor3ub(255, 64,  64);  i++; continue;   // red: important errors
  194.                     case '4': glColor3ub(128, 128, 128); i++; continue;   // gray
  195.                     case '5': glColor3ub(255, 255, 255); i++; continue;   // white: everything else
  196.                     case '6': glColor3ub(192, 64,  192); i++; continue;   // magenta
  197.                     case 's': // save color
  198.                         if((size_t)colorpos<sizeof(colorstack)/sizeof(colorstack[0]))
  199.                         {
  200.                             glEnd();
  201.                             glGetFloatv(GL_CURRENT_COLOR, colorstack[colorpos++]);
  202.                             glBegin(GL_QUADS);
  203.                         }
  204.                         i++;
  205.                         continue;
  206.                     case 'r': // restore color
  207.                         if(colorpos>0)
  208.                             glColor4fv(colorstack[--colorpos]);
  209.                         i++;
  210.                         continue;
  211.                     default: i++; continue;
  212.                 }
  213.  
  214.             case ' ':
  215.                 x += curfont->defaultw;
  216.                 continue;
  217.         }
  218.  
  219.         c -= 33;
  220.         if(!curfont->chars.inrange(c)) continue;
  221.  
  222.         font::charinfo &info = curfont->chars[c];
  223.         float tc_left    = (info.x + curfont->offsetx) / float(curfont->tex->xs);
  224.         float tc_top     = (info.y + curfont->offsety) / float(curfont->tex->ys);
  225.         float tc_right   = (info.x + info.w + curfont->offsetw) / float(curfont->tex->xs);
  226.         float tc_bottom  = (info.y + info.h + curfont->offseth) / float(curfont->tex->ys);
  227.  
  228.         glTexCoord2f(tc_left,  tc_top   ); glVertex2i(x,          y);
  229.         glTexCoord2f(tc_right, tc_top   ); glVertex2i(x + info.w, y);
  230.         glTexCoord2f(tc_right, tc_bottom); glVertex2i(x + info.w, y + info.h);
  231.         glTexCoord2f(tc_left,  tc_bottom); glVertex2i(x,          y + info.h);
  232.  
  233.         xtraverts += 4;
  234.         x += info.w + 1;
  235.     }
  236.     glEnd();
  237. }
  238.  
  239.