3 * Daniel Nelson - 11/10/0
5 * Copyright (C) 2000 Daniel Nelson
6 * Copyright (C) 2004 Andrew Sayman
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
26 * Holds string display utilities.
37 #include "TextureLoader.h"
39 #include "Displayer.h"
42 const char *String::letter_texture_files
[DC_FONT_NUMBER
][DC_LETTER_NUMBER
]
43 = { { GC_DATA_DIRECTORY("font0_0.tga"),
44 GC_DATA_DIRECTORY("font0_1.tga"),
45 GC_DATA_DIRECTORY("font0_2.tga"),
46 GC_DATA_DIRECTORY("font0_3.tga"),
47 GC_DATA_DIRECTORY("font0_4.tga"),
48 GC_DATA_DIRECTORY("font0_5.tga"),
49 GC_DATA_DIRECTORY("font0_6.tga"),
50 GC_DATA_DIRECTORY("font0_7.tga"),
51 GC_DATA_DIRECTORY("font0_8.tga"),
52 GC_DATA_DIRECTORY("font0_9.tga"),
53 GC_DATA_DIRECTORY("font0_ca.tga"),
54 GC_DATA_DIRECTORY("font0_cb.tga"),
55 GC_DATA_DIRECTORY("font0_cc.tga"),
56 GC_DATA_DIRECTORY("font0_cd.tga"),
57 GC_DATA_DIRECTORY("font0_ce.tga"),
58 GC_DATA_DIRECTORY("font0_cf.tga"),
59 GC_DATA_DIRECTORY("font0_cg.tga"),
60 GC_DATA_DIRECTORY("font0_ch.tga"),
61 GC_DATA_DIRECTORY("font0_ci.tga"),
62 GC_DATA_DIRECTORY("font0_cj.tga"),
63 GC_DATA_DIRECTORY("font0_ck.tga"),
64 GC_DATA_DIRECTORY("font0_cl.tga"),
65 GC_DATA_DIRECTORY("font0_cm.tga"),
66 GC_DATA_DIRECTORY("font0_cn.tga"),
67 GC_DATA_DIRECTORY("font0_co.tga"),
68 GC_DATA_DIRECTORY("font0_cp.tga"),
69 GC_DATA_DIRECTORY("font0_cq.tga"),
70 GC_DATA_DIRECTORY("font0_cr.tga"),
71 GC_DATA_DIRECTORY("font0_cs.tga"),
72 GC_DATA_DIRECTORY("font0_ct.tga"),
73 GC_DATA_DIRECTORY("font0_cu.tga"),
74 GC_DATA_DIRECTORY("font0_cv.tga"),
75 GC_DATA_DIRECTORY("font0_cw.tga"),
76 GC_DATA_DIRECTORY("font0_cx.tga"),
77 GC_DATA_DIRECTORY("font0_cy.tga"),
78 GC_DATA_DIRECTORY("font0_cz.tga"),
79 GC_DATA_DIRECTORY("font0_a.tga"),
80 GC_DATA_DIRECTORY("font0_b.tga"),
81 GC_DATA_DIRECTORY("font0_c.tga"),
82 GC_DATA_DIRECTORY("font0_d.tga"),
83 GC_DATA_DIRECTORY("font0_e.tga"),
84 GC_DATA_DIRECTORY("font0_f.tga"),
85 GC_DATA_DIRECTORY("font0_g.tga"),
86 GC_DATA_DIRECTORY("font0_h.tga"),
87 GC_DATA_DIRECTORY("font0_i.tga"),
88 GC_DATA_DIRECTORY("font0_j.tga"),
89 GC_DATA_DIRECTORY("font0_k.tga"),
90 GC_DATA_DIRECTORY("font0_l.tga"),
91 GC_DATA_DIRECTORY("font0_m.tga"),
92 GC_DATA_DIRECTORY("font0_n.tga"),
93 GC_DATA_DIRECTORY("font0_o.tga"),
94 GC_DATA_DIRECTORY("font0_p.tga"),
95 GC_DATA_DIRECTORY("font0_q.tga"),
96 GC_DATA_DIRECTORY("font0_r.tga"),
97 GC_DATA_DIRECTORY("font0_s.tga"),
98 GC_DATA_DIRECTORY("font0_t.tga"),
99 GC_DATA_DIRECTORY("font0_u.tga"),
100 GC_DATA_DIRECTORY("font0_v.tga"),
101 GC_DATA_DIRECTORY("font0_w.tga"),
102 GC_DATA_DIRECTORY("font0_x.tga"),
103 GC_DATA_DIRECTORY("font0_y.tga"),
104 GC_DATA_DIRECTORY("font0_z.tga"),
105 GC_DATA_DIRECTORY("font0_mn.tga"),
106 GC_DATA_DIRECTORY("font0_cln.tga"),
107 GC_DATA_DIRECTORY("font0_pe.tga"),
108 GC_DATA_DIRECTORY("font0_cma.tga"),
109 GC_DATA_DIRECTORY("font0_ep.tga"),
110 GC_DATA_DIRECTORY("font0_at.tga"),
111 GC_DATA_DIRECTORY("font0_td.tga"),
112 GC_DATA_DIRECTORY("font0_pd.tga"),
113 GC_DATA_DIRECTORY("font0_ds.tga"),
114 GC_DATA_DIRECTORY("font0_ps.tga"),
115 GC_DATA_DIRECTORY("font0_and.tga"),
116 GC_DATA_DIRECTORY("font0_pl.tga"),
117 GC_DATA_DIRECTORY("font0_pr.tga"),
118 GC_DATA_DIRECTORY("font0_sl.tga"),
119 GC_DATA_DIRECTORY("font0_lt.tga"),
120 GC_DATA_DIRECTORY("font0_gt.tga"),
121 GC_DATA_DIRECTORY("font0_qm.tga"),
122 GC_DATA_DIRECTORY("font0_eq.tga"),
123 GC_DATA_DIRECTORY("font0_pu.tga"),
124 GC_DATA_DIRECTORY("font0_br.tga"),
125 GC_DATA_DIRECTORY("font0_za.tga"),
126 GC_DATA_DIRECTORY("font0_zb.tga"),
127 GC_DATA_DIRECTORY("font0_zc.tga"),
128 GC_DATA_DIRECTORY("font0_zd.tga") } };
130 const char String::letter_mapping
[DC_LETTER_NUMBER
]
131 = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
133 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
134 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
135 'U', 'V', 'W', 'X', 'Y', 'Z',
137 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
138 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
139 'u', 'v', 'w', 'x', 'y', 'z',
141 '-', ':', '.', ',', '!', '@', '~', '#', '$', '%',
142 '&', '(', ')', '/', '<', '>', '?', '=', '+', '|',
143 ';', '[', '*', ']' };
145 const int String::letter_widths
[DC_FONT_NUMBER
][DC_LETTER_NUMBER
]
146 = { { 20, 12, 17, 14, 16, 15, 16, 19, 17, 16,
148 28, 20, 17, 20, 18, 20, 20, 19, 11, 17,
149 19, 17, 30, 20, 20, 21, 22, 22, 16, 21,
150 20, 20, 30, 25, 22, 19,
152 19, 14, 13, 14, 13, 14, 15, 14, 8, 12,
153 14, 12, 22, 15, 14, 14, 16, 16, 12, 15,
154 14, 15, 22, 18, 17, 13,
156 20, 12, 11, 10, 11, 21, 23, 23, 18, 19,
157 20, 12, 13, 18, 16, 16, 17, 20, 23, 16,
161 const float String::colors
[DC_FONT_COLOR_NUMBER
][3]
162 = { { 0.2f
, 0.2f
, 1.0f
},
163 { 1.0f
, 0.1f
, 0.1f
},
164 { 0.1f
, 1.0f
, 0.1f
},
165 { 0.8f
, 0.8f
, 0.1f
},
166 { 0.9f
, 0.0f
, 0.9f
},
167 { 0.1f
, 0.8f
, 0.8f
},
168 { 0.9f
, 0.3f
, 0.1f
},
169 { 1.0f
, 0.5f
, 0.5f
},
170 { 0.4f
, 0.0f
, 1.0f
},
171 { 0.1f
, 0.1f
, 0.1f
} };
173 GLubyte
*String::letter_textures
[DC_FONT_NUMBER
][DC_LETTER_NUMBER
];
175 int String::mapCharToCode ( char c
)
178 for (int n
= DC_LETTER_NUMBER
; n
--; )
179 if (c
== letter_mapping
[n
]) {
186 int String::stringWidth ( const char *string
, int max_width
)
188 * Determines the pixel width of a string.
194 for (unsigned int n
= 0; n
< strlen(string
) && length
< max_width
; n
++) {
196 if (string
[n
] == '~') {
197 switch (string
[++n
]) {
199 if (length
>= DC_BACK_SPACE_WIDTH
) length
-= DC_BACK_SPACE_WIDTH
;
202 length
+= DC_BACK_SPACE_WIDTH
;
205 int c
= string
[n
] - 'a';
206 if (c
>= 0 && c
< DC_FONT_NUMBER
)
211 if (string
[n
] != '~') continue;
213 } else if (string
[n
] == ' ') {
214 length
+= DC_SPACE_WIDTH
;
218 int code
= mapCharToCode(string
[n
]);
220 if (length
+ letter_widths
[font
][code
] > max_width
) break;
221 length
+= letter_widths
[font
][code
];
228 void String::readyLetterTextures ( )
230 for (int n
= DC_FONT_NUMBER
; n
--; )
231 for (int m
= DC_LETTER_NUMBER
; m
--; )
232 letter_textures
[n
][m
]
233 = TextureLoader::loadAlphaTGA(letter_texture_files
[n
][m
],
234 DC_LETTER_TEX_LENGTH
, DC_LETTER_TEX_LENGTH
);
237 void String::freeLetterTextures ( )
239 for (int n
= DC_FONT_NUMBER
; n
--; )
240 for (int m
= DC_LETTER_NUMBER
; m
--; )
241 if (letter_textures
[n
][m
] != null
) {
242 delete [] letter_textures
[n
][m
];
243 letter_textures
[n
][m
] = null
;
248 void String::fillStringTexture ( const char *string
, GLubyte
*texture
,
249 int width
, bool use_alpha
, int texture_width
)
251 * Fills the memory space pointed to by texture with a string texture. The
252 * texture height must equal DC_LETTER_TEX_LENGTH. readyLetterTextures() must
253 * be called first, and freeLetterTextures() must be called after this
254 * function's final use.
257 if (texture_width
== 0)
258 texture_width
= width
;
260 // initialize texture
262 for (int t
= DC_LETTER_TEX_LENGTH
; t
--; )
263 for (int s
= width
; s
--; ) {
264 texture
[(t
* texture_width
+ s
) * 4 + 0] = 0;
265 texture
[(t
* texture_width
+ s
) * 4 + 1] = 0;
266 texture
[(t
* texture_width
+ s
) * 4 + 2] = 0;
267 texture
[(t
* texture_width
+ s
) * 4 + 3] = 255;
272 int base_color
= DC_DEFAULT_FONT_COLOR
;
273 for (unsigned int n
= 0; n
< strlen(string
) && cursor
< width
; n
++) {
276 if (string
[n
] == '~') {
277 switch (string
[++n
]) {
279 if (cursor
> DC_BACK_SPACE_WIDTH
)
280 cursor
-= DC_BACK_SPACE_WIDTH
;
285 cursor
+= DC_BACK_SPACE_WIDTH
;
289 if (isdigit(string
[n
])) {
290 int c
= string
[n
] - '0';
291 if (c
< DC_FONT_COLOR_NUMBER
)
296 int c
= string
[n
] - 'a';
297 if (c
>= 0 && c
< DC_FONT_NUMBER
)
303 if (string
[n
] != '~') continue;
305 } else if (string
[n
] == ' ') {
306 cursor
+= DC_SPACE_WIDTH
;
310 int code
= mapCharToCode(string
[n
]);
311 if (code
== -1) continue;
313 if (cursor
+ letter_widths
[font
][code
] > width
) break;
317 for (int t
= DC_LETTER_TEX_LENGTH
; t
--; )
318 for (int s
= DC_LETTER_TEX_LENGTH
; s
--; ) {
319 if (cursor
+ s
>= width
) continue;
321 float alpha
= letter_textures
[font
][code
][t
* DC_LETTER_TEX_LENGTH
322 + s
] * (1.0f
/ 255.0f
);
323 for (int c
= 3; c
--; ) {
324 float color
= colors
[base_color
][c
] + (1.0f
- colors
[base_color
][c
])
325 * (DC_LETTER_TEX_LENGTH
- t
+ (s
>= letter_widths
[font
][code
]
326 ? DC_LETTER_TEX_LENGTH
: s
+ (DC_LETTER_TEX_LENGTH
327 - letter_widths
[font
][code
])))
328 * (0.5f
/ (float) DC_LETTER_TEX_LENGTH
);
329 float result
= (255.0f
* color
* alpha
)
330 + texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
];
331 if (result
>= 255.0f
)
332 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
] = (GLubyte
) 255;
334 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
]
340 for (int t
= DC_LETTER_TEX_LENGTH
; t
--; )
341 for (int s
= DC_LETTER_TEX_LENGTH
; s
--; ) {
342 if (cursor
+ s
>= width
)
344 if (letter_textures
[font
][code
][t
* DC_LETTER_TEX_LENGTH
+ s
] == 0)
347 int old_alpha
= texture
[(t
* texture_width
+ cursor
+ s
) * 4 + 3];
348 int new_alpha
= letter_textures
[font
][code
][t
* DC_LETTER_TEX_LENGTH
350 if (new_alpha
+ old_alpha
>= 255)
351 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + 3] = 255;
353 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + 3]
354 = (GLubyte
) (new_alpha
+ old_alpha
);
356 for (int c
= 3; c
--; ) {
357 float color
= colors
[base_color
][c
] + (1.0f
- colors
[base_color
][c
])
358 * (DC_LETTER_TEX_LENGTH
- t
+ (s
>= letter_widths
[font
][code
]
359 ? DC_LETTER_TEX_LENGTH
: s
+ (DC_LETTER_TEX_LENGTH
360 - letter_widths
[font
][code
])))
361 * (0.5f
/ (float) DC_LETTER_TEX_LENGTH
);
362 float result
= (255.0f
* color
) + (old_alpha
* (1.0f
/ 255.0f
))
363 * texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
];
364 if (result
>= 255.0f
)
365 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
] = 255;
367 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
]
372 cursor
+= letter_widths
[font
][code
];