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"
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,
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
)
177 for (int n
= DC_LETTER_NUMBER
; n
--; )
178 if (c
== letter_mapping
[n
]) {
185 int String::stringWidth ( const char *string
, int max_width
)
187 * Determines the pixel width of a string.
193 for (unsigned int n
= 0; n
< strlen(string
) && length
< max_width
; n
++) {
195 if (string
[n
] == '~') {
196 switch (string
[++n
]) {
198 if (length
>= DC_BACK_SPACE_WIDTH
) length
-= DC_BACK_SPACE_WIDTH
;
201 length
+= DC_BACK_SPACE_WIDTH
;
204 int c
= string
[n
] - 'a';
205 if (c
>= 0 && c
< DC_FONT_NUMBER
)
210 if (string
[n
] != '~') continue;
212 } else if (string
[n
] == ' ') {
213 length
+= DC_SPACE_WIDTH
;
217 int code
= mapCharToCode(string
[n
]);
219 if (length
+ letter_widths
[font
][code
] > max_width
) break;
220 length
+= letter_widths
[font
][code
];
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
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;
270 int base_color
= DC_DEFAULT_FONT_COLOR
;
271 for (unsigned int n
= 0; n
< strlen(string
) && cursor
< width
; n
++) {
274 if (string
[n
] == '~') {
275 switch (string
[++n
]) {
277 if (cursor
> DC_BACK_SPACE_WIDTH
)
278 cursor
-= DC_BACK_SPACE_WIDTH
;
283 cursor
+= DC_BACK_SPACE_WIDTH
;
287 if (isdigit(string
[n
])) {
288 int c
= string
[n
] - '0';
289 if (c
< DC_FONT_COLOR_NUMBER
)
294 int c
= string
[n
] - 'a';
295 if (c
>= 0 && c
< DC_FONT_NUMBER
)
301 if (string
[n
] != '~') continue;
303 } else if (string
[n
] == ' ') {
304 cursor
+= DC_SPACE_WIDTH
;
308 int code
= mapCharToCode(string
[n
]);
309 if (code
== -1) continue;
311 if (cursor
+ letter_widths
[font
][code
] > width
) break;
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;
332 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
]
338 for (int t
= DC_LETTER_TEX_LENGTH
; t
--; )
339 for (int s
= DC_LETTER_TEX_LENGTH
; s
--; ) {
340 if (cursor
+ s
>= width
)
342 if (letter_textures
[font
][code
][t
* DC_LETTER_TEX_LENGTH
+ s
] == 0)
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
348 if (new_alpha
+ old_alpha
>= 255)
349 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + 3] = 255;
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;
365 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
]
370 cursor
+= letter_widths
[font
][code
];