Fixes for datatype size on amd64.
[crack-attack.git] / src / String.cxx
blob315c4523ca33faca1b8cff0899ae4019905e9143
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 "String.h"
31 #include <cctype>
32 #include <cstring>
33 #include <GL/glut.h>
35 #include "glext.h"
37 #include "TextureLoader.h"
38 #include "Game.h"
39 #include "Displayer.h"
41 const char *String::letter_texture_files[DC_FONT_NUMBER][DC_LETTER_NUMBER]
42 = { { GC_DATA_DIRECTORY("font0_0.tga"),
43 GC_DATA_DIRECTORY("font0_1.tga"),
44 GC_DATA_DIRECTORY("font0_2.tga"),
45 GC_DATA_DIRECTORY("font0_3.tga"),
46 GC_DATA_DIRECTORY("font0_4.tga"),
47 GC_DATA_DIRECTORY("font0_5.tga"),
48 GC_DATA_DIRECTORY("font0_6.tga"),
49 GC_DATA_DIRECTORY("font0_7.tga"),
50 GC_DATA_DIRECTORY("font0_8.tga"),
51 GC_DATA_DIRECTORY("font0_9.tga"),
52 GC_DATA_DIRECTORY("font0_ca.tga"),
53 GC_DATA_DIRECTORY("font0_cb.tga"),
54 GC_DATA_DIRECTORY("font0_cc.tga"),
55 GC_DATA_DIRECTORY("font0_cd.tga"),
56 GC_DATA_DIRECTORY("font0_ce.tga"),
57 GC_DATA_DIRECTORY("font0_cf.tga"),
58 GC_DATA_DIRECTORY("font0_cg.tga"),
59 GC_DATA_DIRECTORY("font0_ch.tga"),
60 GC_DATA_DIRECTORY("font0_ci.tga"),
61 GC_DATA_DIRECTORY("font0_cj.tga"),
62 GC_DATA_DIRECTORY("font0_ck.tga"),
63 GC_DATA_DIRECTORY("font0_cl.tga"),
64 GC_DATA_DIRECTORY("font0_cm.tga"),
65 GC_DATA_DIRECTORY("font0_cn.tga"),
66 GC_DATA_DIRECTORY("font0_co.tga"),
67 GC_DATA_DIRECTORY("font0_cp.tga"),
68 GC_DATA_DIRECTORY("font0_cq.tga"),
69 GC_DATA_DIRECTORY("font0_cr.tga"),
70 GC_DATA_DIRECTORY("font0_cs.tga"),
71 GC_DATA_DIRECTORY("font0_ct.tga"),
72 GC_DATA_DIRECTORY("font0_cu.tga"),
73 GC_DATA_DIRECTORY("font0_cv.tga"),
74 GC_DATA_DIRECTORY("font0_cw.tga"),
75 GC_DATA_DIRECTORY("font0_cx.tga"),
76 GC_DATA_DIRECTORY("font0_cy.tga"),
77 GC_DATA_DIRECTORY("font0_cz.tga"),
78 GC_DATA_DIRECTORY("font0_a.tga"),
79 GC_DATA_DIRECTORY("font0_b.tga"),
80 GC_DATA_DIRECTORY("font0_c.tga"),
81 GC_DATA_DIRECTORY("font0_d.tga"),
82 GC_DATA_DIRECTORY("font0_e.tga"),
83 GC_DATA_DIRECTORY("font0_f.tga"),
84 GC_DATA_DIRECTORY("font0_g.tga"),
85 GC_DATA_DIRECTORY("font0_h.tga"),
86 GC_DATA_DIRECTORY("font0_i.tga"),
87 GC_DATA_DIRECTORY("font0_j.tga"),
88 GC_DATA_DIRECTORY("font0_k.tga"),
89 GC_DATA_DIRECTORY("font0_l.tga"),
90 GC_DATA_DIRECTORY("font0_m.tga"),
91 GC_DATA_DIRECTORY("font0_n.tga"),
92 GC_DATA_DIRECTORY("font0_o.tga"),
93 GC_DATA_DIRECTORY("font0_p.tga"),
94 GC_DATA_DIRECTORY("font0_q.tga"),
95 GC_DATA_DIRECTORY("font0_r.tga"),
96 GC_DATA_DIRECTORY("font0_s.tga"),
97 GC_DATA_DIRECTORY("font0_t.tga"),
98 GC_DATA_DIRECTORY("font0_u.tga"),
99 GC_DATA_DIRECTORY("font0_v.tga"),
100 GC_DATA_DIRECTORY("font0_w.tga"),
101 GC_DATA_DIRECTORY("font0_x.tga"),
102 GC_DATA_DIRECTORY("font0_y.tga"),
103 GC_DATA_DIRECTORY("font0_z.tga"),
104 GC_DATA_DIRECTORY("font0_mn.tga"),
105 GC_DATA_DIRECTORY("font0_cln.tga"),
106 GC_DATA_DIRECTORY("font0_pe.tga"),
107 GC_DATA_DIRECTORY("font0_cma.tga"),
108 GC_DATA_DIRECTORY("font0_ep.tga"),
109 GC_DATA_DIRECTORY("font0_at.tga"),
110 GC_DATA_DIRECTORY("font0_td.tga"),
111 GC_DATA_DIRECTORY("font0_pd.tga"),
112 GC_DATA_DIRECTORY("font0_ds.tga"),
113 GC_DATA_DIRECTORY("font0_ps.tga"),
114 GC_DATA_DIRECTORY("font0_and.tga"),
115 GC_DATA_DIRECTORY("font0_pl.tga"),
116 GC_DATA_DIRECTORY("font0_pr.tga"),
117 GC_DATA_DIRECTORY("font0_sl.tga"),
118 GC_DATA_DIRECTORY("font0_lt.tga"),
119 GC_DATA_DIRECTORY("font0_gt.tga"),
120 GC_DATA_DIRECTORY("font0_qm.tga"),
121 GC_DATA_DIRECTORY("font0_eq.tga"),
122 GC_DATA_DIRECTORY("font0_pu.tga"),
123 GC_DATA_DIRECTORY("font0_br.tga"),
124 GC_DATA_DIRECTORY("font0_za.tga"),
125 GC_DATA_DIRECTORY("font0_zb.tga"),
126 GC_DATA_DIRECTORY("font0_zc.tga"),
127 GC_DATA_DIRECTORY("font0_zd.tga") } };
129 const char String::letter_mapping[DC_LETTER_NUMBER]
130 = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
132 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
133 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
134 'U', 'V', 'W', 'X', 'Y', 'Z',
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 '-', ':', '.', ',', '!', '@', '~', '#', '$', '%',
141 '&', '(', ')', '/', '<', '>', '?', '=', '+', '|',
142 ';', '[', '*', ']' };
144 const int String::letter_widths[DC_FONT_NUMBER][DC_LETTER_NUMBER]
145 = { { 20, 12, 17, 14, 16, 15, 16, 19, 17, 16,
147 28, 20, 17, 20, 18, 20, 20, 19, 11, 17,
148 19, 17, 30, 20, 20, 21, 22, 22, 16, 21,
149 20, 20, 30, 25, 22, 19,
151 19, 14, 13, 14, 13, 14, 15, 14, 8, 12,
152 14, 12, 22, 15, 14, 14, 16, 16, 12, 15,
153 14, 15, 22, 18, 17, 13,
155 20, 12, 11, 10, 11, 21, 23, 23, 18, 19,
156 20, 12, 13, 18, 16, 16, 17, 20, 23, 16,
157 22, 22, 16, 22 } };
160 const float String::colors[DC_FONT_COLOR_NUMBER][3]
161 = { { 0.2f, 0.2f, 1.0f },
162 { 1.0f, 0.1f, 0.1f },
163 { 0.1f, 1.0f, 0.1f },
164 { 0.8f, 0.8f, 0.1f },
165 { 0.9f, 0.0f, 0.9f },
166 { 0.1f, 0.8f, 0.8f },
167 { 0.9f, 0.3f, 0.1f },
168 { 1.0f, 0.5f, 0.5f },
169 { 0.4f, 0.0f, 1.0f },
170 { 0.1f, 0.1f, 0.1f } };
172 GLubyte *String::letter_textures[DC_FONT_NUMBER][DC_LETTER_NUMBER];
174 int String::mapCharToCode ( char c )
176 int code = -1;
177 for (int n = DC_LETTER_NUMBER; n--; )
178 if (c == letter_mapping[n]) {
179 code = n;
180 break;
182 return code;
185 int String::stringWidth ( const char *string, int max_width )
187 * Determines the pixel width of a string.
190 int length = 0;
192 int font = 0;
193 for (unsigned int n = 0; n < strlen(string) && length < max_width; n++) {
195 if (string[n] == '~') {
196 switch (string[++n]) {
197 case '<':
198 if (length >= DC_BACK_SPACE_WIDTH) length -= DC_BACK_SPACE_WIDTH;
199 break;
200 case '>':
201 length += DC_BACK_SPACE_WIDTH;
202 break;
203 default:
204 int c = string[n] - 'a';
205 if (c >= 0 && c < DC_FONT_NUMBER)
206 font = c;
207 break;
210 if (string[n] != '~') continue;
212 } else if (string[n] == ' ') {
213 length += DC_SPACE_WIDTH;
214 continue;
217 int code = mapCharToCode(string[n]);
218 if (code != -1) {
219 if (length + letter_widths[font][code] > max_width) break;
220 length += letter_widths[font][code];
224 return length;
227 void String::readyLetterTextures ( )
229 for (int n = DC_FONT_NUMBER; n--; )
230 for (int m = DC_LETTER_NUMBER; m--; )
231 letter_textures[n][m]
232 = TextureLoader::loadImageAlpha(letter_texture_files[n][m],
233 DC_LETTER_TEX_LENGTH, DC_LETTER_TEX_LENGTH);
236 void String::freeLetterTextures ( )
238 for (int n = DC_FONT_NUMBER; n--; )
239 for (int m = DC_LETTER_NUMBER; m--; )
240 if (letter_textures[n][m] != null) {
241 delete [] letter_textures[n][m];
242 letter_textures[n][m] = null;
246 void String::fillStringTexture ( const char *string, GLubyte *texture,
247 int width, bool use_alpha, int texture_width )
249 * Fills the memory space pointed to by texture with a string texture. The
250 * texture height must equal DC_LETTER_TEX_LENGTH. readyLetterTextures() must
251 * be called first, and freeLetterTextures() must be called after this
252 * function's final use.
255 if (texture_width == 0)
256 texture_width = width;
258 // initialize texture
259 if (!use_alpha)
260 for (int t = DC_LETTER_TEX_LENGTH; t--; )
261 for (int s = width; s--; ) {
262 texture[(t * texture_width + s) * 4 + 0] = 0;
263 texture[(t * texture_width + s) * 4 + 1] = 0;
264 texture[(t * texture_width + s) * 4 + 2] = 0;
265 texture[(t * texture_width + s) * 4 + 3] = 255;
268 int cursor = 0;
269 int font = 0;
270 int base_color = DC_DEFAULT_FONT_COLOR;
271 for (unsigned int n = 0; n < strlen(string) && cursor < width; n++) {
273 // special cases
274 if (string[n] == '~') {
275 switch (string[++n]) {
276 case '<':
277 if (cursor > DC_BACK_SPACE_WIDTH)
278 cursor -= DC_BACK_SPACE_WIDTH;
279 else
280 cursor = 0;
281 break;
282 case '>':
283 cursor += DC_BACK_SPACE_WIDTH;
284 break;
285 default:
286 // color change
287 if (isdigit(string[n])) {
288 int c = string[n] - '0';
289 if (c < DC_FONT_COLOR_NUMBER)
290 base_color = c;
292 // font change
293 } else {
294 int c = string[n] - 'a';
295 if (c >= 0 && c < DC_FONT_NUMBER)
296 font = c;
298 break;
301 if (string[n] != '~') continue;
303 } else if (string[n] == ' ') {
304 cursor += DC_SPACE_WIDTH;
305 continue;
308 int code = mapCharToCode(string[n]);
309 if (code == -1) continue;
311 if (cursor + letter_widths[font][code] > width) break;
313 // copy letter
314 if (!use_alpha)
315 for (int t = DC_LETTER_TEX_LENGTH; t--; )
316 for (int s = DC_LETTER_TEX_LENGTH; s--; ) {
317 if (cursor + s >= width) continue;
319 float alpha = letter_textures[font][code][t * DC_LETTER_TEX_LENGTH
320 + s] * (1.0f / 255.0f);
321 for (int c = 3; c--; ) {
322 float color = colors[base_color][c] + (1.0f - colors[base_color][c])
323 * (DC_LETTER_TEX_LENGTH - t + (s >= letter_widths[font][code]
324 ? DC_LETTER_TEX_LENGTH : s + (DC_LETTER_TEX_LENGTH
325 - letter_widths[font][code])))
326 * (0.5f / (float) DC_LETTER_TEX_LENGTH);
327 float result = (255.0f * color * alpha)
328 + texture[(t * texture_width + cursor + s) * 4 + c];
329 if (result >= 255.0f)
330 texture[(t * texture_width + cursor + s) * 4 + c] = (GLubyte) 255;
331 else
332 texture[(t * texture_width + cursor + s) * 4 + c]
333 = (GLubyte) result;
337 else
338 for (int t = DC_LETTER_TEX_LENGTH; t--; )
339 for (int s = DC_LETTER_TEX_LENGTH; s--; ) {
340 if (cursor + s >= width)
341 continue;
342 if (letter_textures[font][code][t * DC_LETTER_TEX_LENGTH + s] == 0)
343 continue;
345 int old_alpha = texture[(t * texture_width + cursor + s) * 4 + 3];
346 int new_alpha = letter_textures[font][code][t * DC_LETTER_TEX_LENGTH
347 + s];
348 if (new_alpha + old_alpha >= 255)
349 texture[(t * texture_width + cursor + s) * 4 + 3] = 255;
350 else
351 texture[(t * texture_width + cursor + s) * 4 + 3]
352 = (GLubyte) (new_alpha + old_alpha);
354 for (int c = 3; c--; ) {
355 float color = colors[base_color][c] + (1.0f - colors[base_color][c])
356 * (DC_LETTER_TEX_LENGTH - t + (s >= letter_widths[font][code]
357 ? DC_LETTER_TEX_LENGTH : s + (DC_LETTER_TEX_LENGTH
358 - letter_widths[font][code])))
359 * (0.5f / (float) DC_LETTER_TEX_LENGTH);
360 float result = (255.0f * color) + (old_alpha * (1.0f / 255.0f))
361 * texture[(t * texture_width + cursor + s) * 4 + c];
362 if (result >= 255.0f)
363 texture[(t * texture_width + cursor + s) * 4 + c] = 255;
364 else
365 texture[(t * texture_width + cursor + s) * 4 + c]
366 = (GLubyte) result;
370 cursor += letter_widths[font][code];