~ubuntu-branches/debian/stretch/assaultcube-data/stretch

« back to all changes in this revision

Viewing changes to source/src/rendertext.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gonéri Le Bouder, Ansgar Burchardt, Gonéri Le Bouder
  • Date: 2010-04-02 23:37:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100402233755-kf74fxwlu634o6vg
Tags: 1.0.4+repack1-1
[ Ansgar Burchardt ]
* debian/control: fix typo in short description

[ Gonéri Le Bouder ]
* Upgrade to 1.0.4
* bump standards-version to 3.8.4
* Add Depends: ${misc:Depends} just to avoid a lintian warning
* Add a debian/source/format file for the same reason

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// rendertext.cpp: font rendering
 
2
 
 
3
#include "pch.h"
 
4
#include "cube.h"
 
5
 
 
6
int VIRTW;
 
7
 
 
8
static hashtable<const char *, font> fonts;
 
9
static font *fontdef = NULL;
 
10
 
 
11
font *curfont = NULL;
 
12
 
 
13
void newfont(char *name, char *tex, char *defaultw, char *defaulth, char *offsetx, char *offsety, char *offsetw, char *offseth)
 
14
{
 
15
    font *f = fonts.access(name);
 
16
    if(!f)
 
17
    {
 
18
        name = newstring(name);
 
19
        f = &fonts[name];
 
20
        f->name = name;
 
21
    }
 
22
 
 
23
    f->tex = textureload(tex);
 
24
    f->chars.setsize(0);
 
25
    f->defaultw = ATOI(defaultw);
 
26
    f->defaulth = ATOI(defaulth);
 
27
    f->offsetx = ATOI(offsetx);
 
28
    f->offsety = ATOI(offsety);
 
29
    f->offsetw = ATOI(offsetw);
 
30
    f->offseth = ATOI(offseth);
 
31
 
 
32
    fontdef = f;
 
33
}
 
34
 
 
35
void fontchar(int x, int y, int w, int h)
 
36
{
 
37
    if(!fontdef) return;
 
38
 
 
39
    font::charinfo &c = fontdef->chars.add();
 
40
    c.x = x;
 
41
    c.y = y;
 
42
    c.w = w ? w : fontdef->defaultw;
 
43
    c.h = h ? h : fontdef->defaulth;
 
44
}
 
45
 
 
46
COMMANDN(font, newfont, ARG_8STR);
 
47
COMMANDN(fontchar, fontchar, ARG_4INT);
 
48
 
 
49
bool setfont(const char *name)
 
50
{
 
51
    font *f = fonts.access(name);
 
52
    if(!f) return false;
 
53
    curfont = f;
 
54
    return true;
 
55
}
 
56
 
 
57
int text_width(const char *str) 
 
58
{
 
59
    int width, height;
 
60
    text_bounds(str, width, height);
 
61
    return width;
 
62
}
 
63
 
 
64
void draw_textf(const char *fstr, int left, int top, ...)
 
65
{
 
66
    s_sprintfdlv(str, top, fstr);
 
67
    draw_text(str, left, top);
 
68
}
 
69
 
 
70
static int draw_char(int c, int x, int y)
 
71
{
 
72
    font::charinfo &info = curfont->chars[c-33];
 
73
    float tc_left    = (info.x + curfont->offsetx) / float(curfont->tex->xs);
 
74
    float tc_top     = (info.y + curfont->offsety) / float(curfont->tex->ys);
 
75
    float tc_right   = (info.x + info.w + curfont->offsetw) / float(curfont->tex->xs);
 
76
    float tc_bottom  = (info.y + info.h + curfont->offseth) / float(curfont->tex->ys);
 
77
 
 
78
    glTexCoord2f(tc_left,  tc_top   ); glVertex2f(x,          y);
 
79
    glTexCoord2f(tc_right, tc_top   ); glVertex2f(x + info.w, y);
 
80
    glTexCoord2f(tc_right, tc_bottom); glVertex2f(x + info.w, y + info.h);
 
81
    glTexCoord2f(tc_left,  tc_bottom); glVertex2f(x,          y + info.h);
 
82
 
 
83
    xtraverts += 4;
 
84
    return info.w;
 
85
}
 
86
 
 
87
//stack[sp] is current color index
 
88
static void text_color(char c, char *stack, int size, int &sp, bvec color, int a) 
 
89
{
 
90
    if(c=='s') // save color
 
91
    {   
 
92
        c = stack[sp];
 
93
        if(sp<size-1) stack[++sp] = c;
 
94
    }
 
95
    else
 
96
    {
 
97
        if(c=='r') c = stack[(sp > 0) ? --sp : sp]; // restore color
 
98
        else stack[sp] = c;
 
99
        switch(c)
 
100
        {
 
101
            case '0': color = bvec(64,  255, 128); break;   // green: player talk
 
102
            case '1': color = bvec(96,  160, 255); break;   // blue: team chat
 
103
            case '2': color = bvec(255, 192, 64);  break;   // yellow: gameplay action messages, only actions done by players
 
104
            case '3': color = bvec(255, 64,  64);  break;   // red: important errors and notes
 
105
            case '4': color = bvec(128, 128, 128); break;   // gray
 
106
            case '5': color = bvec(255, 255, 255); break;   // white
 
107
            case '6': color = bvec(96, 48, 0);     break;   // dark brown
 
108
            case '7': color = bvec(128, 48,  48);  break;   // dark red: dead admin
 
109
            // white (provided color): everything else
 
110
        }
 
111
        glColor4ub(color.x, color.y, color.z, a);
 
112
    } 
 
113
}
 
114
 
 
115
static vector<int> *columns = NULL;
 
116
 
 
117
void text_startcolumns()
 
118
{
 
119
    if(!columns) columns = new vector<int>;
 
120
}
 
121
 
 
122
void text_endcolumns()
 
123
{
 
124
    DELETEP(columns);
 
125
}
 
126
 
 
127
#define TABALIGN(x) ((((x)+PIXELTAB)/PIXELTAB)*PIXELTAB)
 
128
 
 
129
#define TEXTGETCOLUMN \
 
130
    if(columns && col<columns->length()) \
 
131
    { \
 
132
        colx += (*columns)[col++]; \
 
133
        x = colx; \
 
134
    } \
 
135
    else x = TABALIGN(x);
 
136
 
 
137
#define TEXTSETCOLUMN \
 
138
    if(columns) \
 
139
    { \
 
140
        while(col>=columns->length()) columns->add(0); \
 
141
        int w = TABALIGN(x) - colx; \
 
142
        w = max(w, (*columns)[col]); \
 
143
        (*columns)[col] = w; \
 
144
        col++; \
 
145
        colx += w; \
 
146
        x = colx; \
 
147
    } \
 
148
    else x = TABALIGN(x);
 
149
 
 
150
 
 
151
#define TEXTSKELETON \
 
152
    int y = 0, x = 0, col = 0, colx = 0;\
 
153
    int i;\
 
154
    for(i = 0; str[i]; i++)\
 
155
    {\
 
156
        TEXTINDEX(i)\
 
157
        int c = str[i];\
 
158
        if(c=='\t')      { TEXTTAB(i); TEXTWHITE(i) }\
 
159
        else if(c==' ')  { x += curfont->defaultw; TEXTWHITE(i) }\
 
160
        else if(c=='\n') { TEXTLINE(i) x = 0; y += FONTH; }\
 
161
        else if(c=='\f') { if(str[i+1]) { i++; TEXTCOLOR(i) }}\
 
162
        else if(curfont->chars.inrange(c-33))\
 
163
        {\
 
164
            if(maxwidth != -1)\
 
165
            {\
 
166
                int j = i;\
 
167
                int w = curfont->chars[c-33].w;\
 
168
                for(; str[i+1]; i++)\
 
169
                {\
 
170
                    int c = str[i+1];\
 
171
                    if(c=='\f') { if(str[i+2]) i++; continue; }\
 
172
                    if(i-j > 16) break;\
 
173
                    if(!curfont->chars.inrange(c-33)) break;\
 
174
                    int cw = curfont->chars[c-33].w + 1;\
 
175
                    if(w + cw >= maxwidth) break;\
 
176
                    w += cw;\
 
177
                }\
 
178
                if(x + w >= maxwidth && j!=0) { TEXTLINE(j-1) x = 0; y += FONTH; }\
 
179
                TEXTWORD\
 
180
            }\
 
181
            else\
 
182
            { TEXTCHAR(i) }\
 
183
        }\
 
184
    }
 
185
 
 
186
//all the chars are guaranteed to be either drawable or color commands
 
187
#define TEXTWORDSKELETON \
 
188
                for(; j <= i; j++)\
 
189
                {\
 
190
                    TEXTINDEX(j)\
 
191
                    int c = str[j];\
 
192
                    if(c=='\f') { if(str[j+1]) { j++; TEXTCOLOR(j) }}\
 
193
                    else { TEXTCHAR(j) }\
 
194
                }
 
195
 
 
196
int text_visible(const char *str, int hitx, int hity, int maxwidth)
 
197
{
 
198
    #define TEXTINDEX(idx)
 
199
    #define TEXTTAB(idx) TEXTGETCOLUMN
 
200
    #define TEXTWHITE(idx) if(y+FONTH > hity && x >= hitx) return idx;
 
201
    #define TEXTLINE(idx) if(y+FONTH > hity) return idx;
 
202
    #define TEXTCOLOR(idx)
 
203
    #define TEXTCHAR(idx) x += curfont->chars[c-33].w+1; TEXTWHITE(idx)
 
204
    #define TEXTWORD TEXTWORDSKELETON
 
205
    TEXTSKELETON
 
206
    #undef TEXTINDEX
 
207
    #undef TEXTTAB
 
208
    #undef TEXTWHITE
 
209
    #undef TEXTLINE
 
210
    #undef TEXTCOLOR
 
211
    #undef TEXTCHAR
 
212
    #undef TEXTWORD
 
213
    return i;
 
214
}
 
215
 
 
216
//inverse of text_visible
 
217
void text_pos(const char *str, int cursor, int &cx, int &cy, int maxwidth) 
 
218
{
 
219
    #define TEXTINDEX(idx) if(idx == cursor) { cx = x; cy = y; break; }
 
220
    #define TEXTTAB(idx) TEXTGETCOLUMN
 
221
    #define TEXTWHITE(idx)
 
222
    #define TEXTLINE(idx)
 
223
    #define TEXTCOLOR(idx)
 
224
    #define TEXTCHAR(idx) x += curfont->chars[c-33].w + 1;
 
225
    #define TEXTWORD TEXTWORDSKELETON if(i >= cursor) break;
 
226
    cx = INT_MIN;
 
227
    cy = 0;
 
228
    TEXTSKELETON
 
229
    if(cx == INT_MIN) { cx = x; cy = y; }
 
230
    #undef TEXTINDEX
 
231
    #undef TEXTTAB
 
232
    #undef TEXTWHITE
 
233
    #undef TEXTLINE
 
234
    #undef TEXTCOLOR
 
235
    #undef TEXTCHAR
 
236
    #undef TEXTWORD
 
237
}
 
238
 
 
239
void text_bounds(const char *str, int &width, int &height, int maxwidth)
 
240
{
 
241
    #define TEXTINDEX(idx)
 
242
    #define TEXTTAB(idx) TEXTSETCOLUMN
 
243
    #define TEXTWHITE(idx)
 
244
    #define TEXTLINE(idx) if(x > width) width = x;
 
245
    #define TEXTCOLOR(idx)
 
246
    #define TEXTCHAR(idx) x += curfont->chars[c-33].w + 1;
 
247
    #define TEXTWORD x += w + 1;
 
248
    width = 0;
 
249
    TEXTSKELETON
 
250
    height = y + FONTH;
 
251
    TEXTLINE(_)
 
252
    #undef TEXTINDEX
 
253
    #undef TEXTTAB
 
254
    #undef TEXTWHITE
 
255
    #undef TEXTLINE
 
256
    #undef TEXTCOLOR
 
257
    #undef TEXTCHAR
 
258
    #undef TEXTWORD
 
259
}
 
260
 
 
261
void draw_text(const char *str, int left, int top, int r, int g, int b, int a, int cursor, int maxwidth) 
 
262
{
 
263
    #define TEXTINDEX(idx) if(idx == cursor) { cx = x; cy = y; cc = str[idx]; }
 
264
    #define TEXTTAB(idx) TEXTGETCOLUMN
 
265
    #define TEXTWHITE(idx)
 
266
    #define TEXTLINE(idx) 
 
267
    #define TEXTCOLOR(idx) text_color(str[idx], colorstack, sizeof(colorstack), colorpos, color, a);
 
268
    #define TEXTCHAR(idx) x += draw_char(c, left+x, top+y)+1;
 
269
    #define TEXTWORD TEXTWORDSKELETON
 
270
    char colorstack[10];
 
271
    bvec color(r, g, b);
 
272
    int colorpos = 0, cx = INT_MIN, cy = 0, cc = ' ';
 
273
    colorstack[0] = 'c'; //indicate user color
 
274
    glBlendFunc(GL_SRC_ALPHA, curfont->tex->bpp==32 ? GL_ONE_MINUS_SRC_ALPHA : GL_ONE);
 
275
    glBindTexture(GL_TEXTURE_2D, curfont->tex->id);
 
276
    glBegin(GL_QUADS);
 
277
    glColor4ub(color.x, color.y, color.z, a);
 
278
    TEXTSKELETON
 
279
    glEnd();
 
280
    if(cursor >= 0)
 
281
    {
 
282
        if(cx == INT_MIN) { cx = x; cy = y; }
 
283
        if(maxwidth != -1 && cx >= maxwidth) { cx = 0; cy += FONTH; }
 
284
        int cw = curfont->chars.inrange(cc-33) ? curfont->chars[cc-33].w + 1 : curfont->defaultw;
 
285
        rendercursor(left+cx, top+cy, cw);
 
286
    }
 
287
    #undef TEXTINDEX
 
288
    #undef TEXTTAB
 
289
    #undef TEXTWHITE
 
290
    #undef TEXTLINE
 
291
    #undef TEXTCOLOR
 
292
    #undef TEXTCHAR
 
293
    #undef TEXTWORD
 
294
}
 
295
 
 
296
void reloadfonts()
 
297
{
 
298
    enumerate(fonts, font, f,
 
299
        if(!reloadtexture(*f.tex)) fatal("failed to reload font texture");
 
300
    );
 
301
}
 
302