Files
assaultcube-/source/src/rendertext.cpp
T
driAn edd181435d no message
git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@979 e016b1c5-ed68-44aa-a2f7-31cac88cffde
2007-04-26 20:09:57 +00:00

265 lines
7.0 KiB
C++

// rendertext.cpp: font rendering
#include "cube.h"
short char_coords[96][4] =
{
{0,0,25,64}, //!
{25,0,54,64}, //"
{54,0,107,64}, //#
{107,0,148,64}, //$
{148,0,217,64}, //%
{217,0,263,64}, //&
{263,0,280,64}, //'
{280,0,309,64}, //(
{309,0,338,64}, //)
{338,0,379,64}, //*
{379,0,432,64}, //+
{432,0,455,64}, //,
{455,0,484,64}, //-
{0,64,21,128}, //.
{23,64,52,128}, ///
{52,64,93,128}, //0
{93,64,133,128}, //1
{133,64,174,128}, //2
{174,64,215,128}, //3
{215,64,256,128}, //4
{256,64,296,128}, //5
{296,64,337,128}, //6
{337,64,378,128}, //7
{378,64,419,128}, //8
{419,64,459,128}, //9
{459,64,488,128}, //:
{0,128,29,192}, //;
{29,128,81,192}, //<
{81,128,134,192}, //=
{134,128,186,192}, //>
{186,128,221,192}, //?
{221,128,285,192}, //@
{285,128,329,192}, //A
{329,128,373,192}, //B
{373,128,418,192}, //C
{418,128,467,192}, //D
{0,192,40,256}, //E
{40,192,77,256}, //F
{77,192,127,256}, //G
{127,192,175,256}, //H
{175,192,202,256}, //I
{202,192,231,256}, //J
{231,192,275,256}, //K
{275,192,311,256}, //L
{311,192,365,256}, //M
{365,192,413,256}, //N
{413,192,463,256}, //O
{1,256,38,320}, //P
{38,256,89,320}, //Q
{89,256,133,320}, //R
{133,256,176,320}, //S
{177,256,216,320}, //T
{217,256,263,320}, //U
{263,256,307,320}, //V
{307,256,370,320}, //W
{370,256,414,320}, //X
{414,256,453,320}, //Y
{453,256,497,320}, //Z
{0,320,29,384}, //[
{29,320,58,384}, //"\"
{59,320,87,384}, //]
{87,320,139,384}, //^
{139,320,180,384}, //_
{180,320,221,384}, //`
{221,320,259,384}, //a
{259,320,299,384}, //b
{299,320,332,384}, //c
{332,320,372,384}, //d
{372,320,411,384}, //e
{411,320,433,384}, //f
{435,320,473,384}, //g
{0,384,40,448}, //h
{40,384,56,448}, //i
{58,384,80,448}, //j
{80,384,118,448}, //k
{118,384,135,448}, //l
{135,384,197,448}, //m
{197,384,238,448}, //n
{238,384,277,448}, //o
{277,384,317,448}, //p
{317,384,356,448}, //q
{357,384,384,448}, //r
{385,384,417,448}, //s
{417,384,442,448}, //t
{443,384,483,448}, //u
{0,448,38,512}, //v
{38,448,90,512}, //w
{90,448,128,512}, //x
{128,448,166,512}, //y
{166,448,200,512}, //z
{200,448,241,512}, //{
{241,448,270,512}, //|
{270,448,310,512}, //}
{310,448,363,512}, //~
};
int char_width(int c, int x)
{
if(c=='\t') x = (x+PIXELTAB)/PIXELTAB*PIXELTAB;
else if(c==' ') x += FONTH/2;
else if(c>=33 && c<=126)
{
c -= 33;
int in_width = char_coords[c][2] - char_coords[c][0];
x += in_width + 1;
}
return x;
}
static vector<int> *columns = NULL;
void text_startcolumns()
{
if(!columns) columns = new vector<int>;
}
void text_endcolumns()
{
DELETEP(columns);
}
int text_width(const char *str, int limit)
{
int x = 0, col = 0;
for(int i = 0; str[i] && (limit<0 || i<limit); i++)
{
switch(str[i])
{
case '\f':
i++;
break;
case '\t':
x = char_width('\t', x);
if(columns)
{
while(col>=columns->length()) columns->add(0);
x = max(x, (*columns)[col]);
(*columns)[col] = x;
col++;
}
break;
default:
x = char_width(str[i], x);
break;
}
}
return x;
}
int text_visible(const char *str, int max)
{
int i = 0, x = 0;
while(str[i])
{
if(str[i]=='\f')
{
i += 2;
continue;
}
x = char_width(str[i], x);
if(x > max) return i;
++i;
}
return i;
}
// cut strings to fit on screen
vector<char *> text_block(const char *str, int max)
{
vector<char *> lines;
int visible;
while((visible = text_visible(str, max)))
{
const char *newline = (const char *)memchr(str, '\n', visible);
if(newline) visible = newline+1-str;
else if(str[visible]) // wrap words
{
int v = visible;
while(v > 0 && str[v] != ' ') v--;
if(v) visible = v+1;
}
char *t = lines.add(newstring((size_t)visible));
s_strncpy(t, str, visible+1);
str += visible;
}
return lines;
}
void draw_textf(const char *fstr, int left, int top, ...)
{
s_sprintfdlv(str, top, fstr);
draw_text(str, left, top);
}
void draw_text(const char *str, int left, int top)
{
static Texture *charstex = NULL;
if(!charstex) charstex = textureload("packages/misc/chars.png");
glBlendFunc(GL_ONE, GL_ONE);
glBindTexture(GL_TEXTURE_2D, charstex->id);
glColor3ub(255, 255, 255);
int x = left, y = top, col = 0;
float in_left, in_top, in_right, in_bottom;
int in_width, in_height;
for (int i = 0; str[i]; i++)
{
int c = str[i];
switch(c)
{
case '\t':
if(columns && col<columns->length()) x = left + (*columns)[col++];
else x = (x-left+PIXELTAB)/PIXELTAB*PIXELTAB+left;
continue;
case '\f':
switch(str[i+1])
{
case '0': glColor3ub(64, 255, 128); i++; continue; // green: player talk
case '1': glColor3ub(96, 160, 255); i++; continue; // blue: team chat
case '2': glColor3ub(255, 192, 64); i++; continue; // yellow: gameplay action messages, only actions done by players
case '3': glColor3ub(255, 64, 64); i++; continue; // red: important errors
case '4': glColor3ub(128, 128, 128); i++; continue; // gray
case '5': glColor3ub(255, 255, 255); i++; continue; // white: everything else
default: i++; continue;
}
case ' ':
x += FONTH/2;
continue;
}
c -= 33;
if(c<0 || c>=95) continue;
in_left = ((float) char_coords[c][0]) / 512.0f;
in_top = ((float) char_coords[c][1]+2) / 512.0f;
in_right = ((float) char_coords[c][2]) / 512.0f;
in_bottom = ((float) char_coords[c][3]-2) / 512.0f;
in_width = char_coords[c][2] - char_coords[c][0];
in_height = char_coords[c][3] - char_coords[c][1];
glBegin(GL_QUADS);
glTexCoord2f(in_left, in_top ); glVertex2i(x, y);
glTexCoord2f(in_right, in_top ); glVertex2i(x + in_width, y);
glTexCoord2f(in_right, in_bottom); glVertex2i(x + in_width, y + in_height);
glTexCoord2f(in_left, in_bottom); glVertex2i(x, y + in_height);
glEnd();
xtraverts += 4;
x += in_width + 1;
}
}