Didn't set the version as a string
[crack-attack.git] / src / String.cxx
blob38296054419483a5ace9628ec10f6ebac3c1172b
1 /*
2 * String.cxx
3 * Daniel Nelson - 11/10/0
5 * Copyright (C) 2000 Daniel Nelson
6 * Copyright (C) 2004 Andrew Sayman
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * Daniel Nelson - aluminumangel.org
23 * 174 W. 18th Ave.
24 * Columbus, OH 43210
26 * Holds string display utilities.
29 #include <cctype>
30 #include <cstring>
31 #include <GL/glut.h>
33 #ifndef _WIN32
34 #else
35 # include <glext.h>
36 #endif
38 using namespace std;
40 #include "TextureLoader.h"
41 #include "Game.h"
42 #include "Displayer.h"
43 #include "String.h"
45 const char *String::letter_texture_files[DC_FONT_NUMBER][DC_LETTER_NUMBER]
46 = { { GC_DATA_DIRECTORY "font0_0.tga",
47 GC_DATA_DIRECTORY "font0_1.tga",
48 GC_DATA_DIRECTORY "font0_2.tga",
49 GC_DATA_DIRECTORY "font0_3.tga",
50 GC_DATA_DIRECTORY "font0_4.tga",
51 GC_DATA_DIRECTORY "font0_5.tga",
52 GC_DATA_DIRECTORY "font0_6.tga",
53 GC_DATA_DIRECTORY "font0_7.tga",
54 GC_DATA_DIRECTORY "font0_8.tga",
55 GC_DATA_DIRECTORY "font0_9.tga",
56 GC_DATA_DIRECTORY "font0_ca.tga",
57 GC_DATA_DIRECTORY "font0_cb.tga",
58 GC_DATA_DIRECTORY "font0_cc.tga",
59 GC_DATA_DIRECTORY "font0_cd.tga",
60 GC_DATA_DIRECTORY "font0_ce.tga",
61 GC_DATA_DIRECTORY "font0_cf.tga",
62 GC_DATA_DIRECTORY "font0_cg.tga",
63 GC_DATA_DIRECTORY "font0_ch.tga",
64 GC_DATA_DIRECTORY "font0_ci.tga",
65 GC_DATA_DIRECTORY "font0_cj.tga",
66 GC_DATA_DIRECTORY "font0_ck.tga",
67 GC_DATA_DIRECTORY "font0_cl.tga",
68 GC_DATA_DIRECTORY "font0_cm.tga",
69 GC_DATA_DIRECTORY "font0_cn.tga",
70 GC_DATA_DIRECTORY "font0_co.tga",
71 GC_DATA_DIRECTORY "font0_cp.tga",
72 GC_DATA_DIRECTORY "font0_cq.tga",
73 GC_DATA_DIRECTORY "font0_cr.tga",
74 GC_DATA_DIRECTORY "font0_cs.tga",
75 GC_DATA_DIRECTORY "font0_ct.tga",
76 GC_DATA_DIRECTORY "font0_cu.tga",
77 GC_DATA_DIRECTORY "font0_cv.tga",
78 GC_DATA_DIRECTORY "font0_cw.tga",
79 GC_DATA_DIRECTORY "font0_cx.tga",
80 GC_DATA_DIRECTORY "font0_cy.tga",
81 GC_DATA_DIRECTORY "font0_cz.tga",
82 GC_DATA_DIRECTORY "font0_a.tga",
83 GC_DATA_DIRECTORY "font0_b.tga",
84 GC_DATA_DIRECTORY "font0_c.tga",
85 GC_DATA_DIRECTORY "font0_d.tga",
86 GC_DATA_DIRECTORY "font0_e.tga",
87 GC_DATA_DIRECTORY "font0_f.tga",
88 GC_DATA_DIRECTORY "font0_g.tga",
89 GC_DATA_DIRECTORY "font0_h.tga",
90 GC_DATA_DIRECTORY "font0_i.tga",
91 GC_DATA_DIRECTORY "font0_j.tga",
92 GC_DATA_DIRECTORY "font0_k.tga",
93 GC_DATA_DIRECTORY "font0_l.tga",
94 GC_DATA_DIRECTORY "font0_m.tga",
95 GC_DATA_DIRECTORY "font0_n.tga",
96 GC_DATA_DIRECTORY "font0_o.tga",
97 GC_DATA_DIRECTORY "font0_p.tga",
98 GC_DATA_DIRECTORY "font0_q.tga",
99 GC_DATA_DIRECTORY "font0_r.tga",
100 GC_DATA_DIRECTORY "font0_s.tga",
101 GC_DATA_DIRECTORY "font0_t.tga",
102 GC_DATA_DIRECTORY "font0_u.tga",
103 GC_DATA_DIRECTORY "font0_v.tga",
104 GC_DATA_DIRECTORY "font0_w.tga",
105 GC_DATA_DIRECTORY "font0_x.tga",
106 GC_DATA_DIRECTORY "font0_y.tga",
107 GC_DATA_DIRECTORY "font0_z.tga",
108 GC_DATA_DIRECTORY "font0_mn.tga",
109 GC_DATA_DIRECTORY "font0_cln.tga",
110 GC_DATA_DIRECTORY "font0_pe.tga",
111 GC_DATA_DIRECTORY "font0_cma.tga",
112 GC_DATA_DIRECTORY "font0_ep.tga",
113 GC_DATA_DIRECTORY "font0_at.tga",
114 GC_DATA_DIRECTORY "font0_td.tga",
115 GC_DATA_DIRECTORY "font0_pd.tga",
116 GC_DATA_DIRECTORY "font0_ds.tga",
117 GC_DATA_DIRECTORY "font0_ps.tga",
118 GC_DATA_DIRECTORY "font0_and.tga",
119 GC_DATA_DIRECTORY "font0_pl.tga",
120 GC_DATA_DIRECTORY "font0_pr.tga",
121 GC_DATA_DIRECTORY "font0_sl.tga",
122 GC_DATA_DIRECTORY "font0_lt.tga",
123 GC_DATA_DIRECTORY "font0_gt.tga",
124 GC_DATA_DIRECTORY "font0_qm.tga",
125 GC_DATA_DIRECTORY "font0_eq.tga",
126 GC_DATA_DIRECTORY "font0_pu.tga",
127 GC_DATA_DIRECTORY "font0_br.tga",
128 GC_DATA_DIRECTORY "font0_za.tga",
129 GC_DATA_DIRECTORY "font0_zb.tga",
130 GC_DATA_DIRECTORY "font0_zc.tga",
131 GC_DATA_DIRECTORY "font0_zd.tga" } };
133 const char String::letter_mapping[DC_LETTER_NUMBER]
134 = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
136 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
137 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
138 'U', 'V', 'W', 'X', 'Y', 'Z',
140 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
141 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
142 'u', 'v', 'w', 'x', 'y', 'z',
144 '-', ':', '.', ',', '!', '@', '~', '#', '$', '%',
145 '&', '(', ')', '/', '<', '>', '?', '=', '+', '|',
146 ';', '[', '*', ']' };
148 const int String::letter_widths[DC_FONT_NUMBER][DC_LETTER_NUMBER]
149 = { { 20, 12, 17, 14, 16, 15, 16, 19, 17, 16,
151 28, 20, 17, 20, 18, 20, 20, 19, 11, 17,
152 19, 17, 30, 20, 20, 21, 22, 22, 16, 21,
153 20, 20, 30, 25, 22, 19,
155 19, 14, 13, 14, 13, 14, 15, 14, 8, 12,
156 14, 12, 22, 15, 14, 14, 16, 16, 12, 15,
157 14, 15, 22, 18, 17, 13,
159 20, 12, 11, 10, 11, 21, 23, 23, 18, 19,
160 20, 12, 13, 18, 16, 16, 17, 20, 23, 16,
161 22, 22, 16, 22 } };
164 const float String::colors[DC_FONT_COLOR_NUMBER][3]
165 = { { 0.2f, 0.2f, 1.0f },
166 { 1.0f, 0.1f, 0.1f },
167 { 0.1f, 1.0f, 0.1f },
168 { 0.8f, 0.8f, 0.1f },
169 { 0.9f, 0.0f, 0.9f },
170 { 0.1f, 0.8f, 0.8f },
171 { 0.9f, 0.3f, 0.1f },
172 { 1.0f, 0.5f, 0.5f },
173 { 0.4f, 0.0f, 1.0f },
174 { 0.1f, 0.1f, 0.1f } };
176 GLubyte *String::letter_textures[DC_FONT_NUMBER][DC_LETTER_NUMBER];
178 int String::mapCharToCode ( char c )
180 int code = -1;
181 for (int n = DC_LETTER_NUMBER; n--; )
182 if (c == letter_mapping[n]) {
183 code = n;
184 break;
186 return code;
189 int String::stringWidth ( const char *string, int max_width )
191 * Determines the pixel width of a string.
194 int length = 0;
196 int font = 0;
197 for (unsigned int n = 0; n < strlen(string) && length < max_width; n++) {
199 if (string[n] == '~') {
200 switch (string[++n]) {
201 case '<':
202 if (length >= DC_BACK_SPACE_WIDTH) length -= DC_BACK_SPACE_WIDTH;
203 break;
204 case '>':
205 length += DC_BACK_SPACE_WIDTH;
206 break;
207 default:
208 int c = string[n] - 'a';
209 if (c >= 0 && c < DC_FONT_NUMBER)
210 font = c;
211 break;
214 if (string[n] != '~') continue;
216 } else if (string[n] == ' ') {
217 length += DC_SPACE_WIDTH;
218 continue;
221 int code = mapCharToCode(string[n]);
222 if (code != -1) {
223 if (length + letter_widths[font][code] > max_width) break;
224 length += letter_widths[font][code];
228 return length;
231 void String::readyLetterTextures ( )
233 for (int n = DC_FONT_NUMBER; n--; )
234 for (int m = DC_LETTER_NUMBER; m--; )
235 letter_textures[n][m]
236 = TextureLoader::loadAlphaTGA(letter_texture_files[n][m],
237 DC_LETTER_TEX_LENGTH, DC_LETTER_TEX_LENGTH);
240 void String::freeLetterTextures ( )
242 for (int n = DC_FONT_NUMBER; n--; )
243 for (int m = DC_LETTER_NUMBER; m--; )
244 if (letter_textures[n][m] != null) {
245 delete [] letter_textures[n][m];
246 letter_textures[n][m] = null;
251 void String::fillStringTexture ( const char *string, GLubyte *texture,
252 int width, bool use_alpha, int texture_width )
254 * Fills the memory space pointed to by texture with a string texture. The
255 * texture height must equal DC_LETTER_TEX_LENGTH. readyLetterTextures() must
256 * be called first, and freeLetterTextures() must be called after this
257 * function's final use.
260 if (texture_width == 0)
261 texture_width = width;
263 // initialize texture
264 if (!use_alpha)
265 for (int t = DC_LETTER_TEX_LENGTH; t--; )
266 for (int s = width; s--; ) {
267 texture[(t * texture_width + s) * 4 + 0] = 0;
268 texture[(t * texture_width + s) * 4 + 1] = 0;
269 texture[(t * texture_width + s) * 4 + 2] = 0;
270 texture[(t * texture_width + s) * 4 + 3] = 255;
273 int cursor = 0;
274 int font = 0;
275 int base_color = DC_DEFAULT_FONT_COLOR;
276 for (unsigned int n = 0; n < strlen(string) && cursor < width; n++) {
278 // special cases
279 if (string[n] == '~') {
280 switch (string[++n]) {
281 case '<':
282 if (cursor > DC_BACK_SPACE_WIDTH)
283 cursor -= DC_BACK_SPACE_WIDTH;
284 else
285 cursor = 0;
286 break;
287 case '>':
288 cursor += DC_BACK_SPACE_WIDTH;
289 break;
290 default:
291 // color change
292 if (isdigit(string[n])) {
293 int c = string[n] - '0';
294 if (c < DC_FONT_COLOR_NUMBER)
295 base_color = c;
297 // font change
298 } else {
299 int c = string[n] - 'a';
300 if (c >= 0 && c < DC_FONT_NUMBER)
301 font = c;
303 break;
306 if (string[n] != '~') continue;
308 } else if (string[n] == ' ') {
309 cursor += DC_SPACE_WIDTH;
310 continue;
313 int code = mapCharToCode(string[n]);
314 if (code == -1) continue;
316 if (cursor + letter_widths[font][code] > width) break;
318 // copy letter
319 if (!use_alpha)
320 for (int t = DC_LETTER_TEX_LENGTH; t--; )
321 for (int s = DC_LETTER_TEX_LENGTH; s--; ) {
322 if (cursor + s >= width) continue;
324 float alpha = letter_textures[font][code][t * DC_LETTER_TEX_LENGTH
325 + s] * (1.0f / 255.0f);
326 for (int c = 3; c--; ) {
327 float color = colors[base_color][c] + (1.0f - colors[base_color][c])
328 * (DC_LETTER_TEX_LENGTH - t + (s >= letter_widths[font][code]
329 ? DC_LETTER_TEX_LENGTH : s + (DC_LETTER_TEX_LENGTH
330 - letter_widths[font][code])))
331 * (0.5f / (float) DC_LETTER_TEX_LENGTH);
332 float result = (255.0f * color * alpha)
333 + texture[(t * texture_width + cursor + s) * 4 + c];
334 if (result >= 255.0f)
335 texture[(t * texture_width + cursor + s) * 4 + c] = (GLubyte) 255;
336 else
337 texture[(t * texture_width + cursor + s) * 4 + c]
338 = (GLubyte) result;
342 else
343 for (int t = DC_LETTER_TEX_LENGTH; t--; )
344 for (int s = DC_LETTER_TEX_LENGTH; s--; ) {
345 if (cursor + s >= width)
346 continue;
347 if (letter_textures[font][code][t * DC_LETTER_TEX_LENGTH + s] == 0)
348 continue;
350 int old_alpha = texture[(t * texture_width + cursor + s) * 4 + 3];
351 int new_alpha = letter_textures[font][code][t * DC_LETTER_TEX_LENGTH
352 + s];
353 if (new_alpha + old_alpha >= 255)
354 texture[(t * texture_width + cursor + s) * 4 + 3] = 255;
355 else
356 texture[(t * texture_width + cursor + s) * 4 + 3]
357 = (GLubyte) (new_alpha + old_alpha);
359 for (int c = 3; c--; ) {
360 float color = colors[base_color][c] + (1.0f - colors[base_color][c])
361 * (DC_LETTER_TEX_LENGTH - t + (s >= letter_widths[font][code]
362 ? DC_LETTER_TEX_LENGTH : s + (DC_LETTER_TEX_LENGTH
363 - letter_widths[font][code])))
364 * (0.5f / (float) DC_LETTER_TEX_LENGTH);
365 float result = (255.0f * color) + (old_alpha * (1.0f / 255.0f))
366 * texture[(t * texture_width + cursor + s) * 4 + c];
367 if (result >= 255.0f)
368 texture[(t * texture_width + cursor + s) * 4 + c] = 255;
369 else
370 texture[(t * texture_width + cursor + s) * 4 + c]
371 = (GLubyte) result;
375 cursor += letter_widths[font][code];