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::loadAlphaTGA(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
;
247 void String::fillStringTexture ( const char *string
, GLubyte
*texture
,
248 int width
, bool use_alpha
, int texture_width
)
250 * Fills the memory space pointed to by texture with a string texture. The
251 * texture height must equal DC_LETTER_TEX_LENGTH. readyLetterTextures() must
252 * be called first, and freeLetterTextures() must be called after this
253 * function's final use.
256 if (texture_width
== 0)
257 texture_width
= width
;
259 // initialize texture
261 for (int t
= DC_LETTER_TEX_LENGTH
; t
--; )
262 for (int s
= width
; s
--; ) {
263 texture
[(t
* texture_width
+ s
) * 4 + 0] = 0;
264 texture
[(t
* texture_width
+ s
) * 4 + 1] = 0;
265 texture
[(t
* texture_width
+ s
) * 4 + 2] = 0;
266 texture
[(t
* texture_width
+ s
) * 4 + 3] = 255;
271 int base_color
= DC_DEFAULT_FONT_COLOR
;
272 for (unsigned int n
= 0; n
< strlen(string
) && cursor
< width
; n
++) {
275 if (string
[n
] == '~') {
276 switch (string
[++n
]) {
278 if (cursor
> DC_BACK_SPACE_WIDTH
)
279 cursor
-= DC_BACK_SPACE_WIDTH
;
284 cursor
+= DC_BACK_SPACE_WIDTH
;
288 if (isdigit(string
[n
])) {
289 int c
= string
[n
] - '0';
290 if (c
< DC_FONT_COLOR_NUMBER
)
295 int c
= string
[n
] - 'a';
296 if (c
>= 0 && c
< DC_FONT_NUMBER
)
302 if (string
[n
] != '~') continue;
304 } else if (string
[n
] == ' ') {
305 cursor
+= DC_SPACE_WIDTH
;
309 int code
= mapCharToCode(string
[n
]);
310 if (code
== -1) continue;
312 if (cursor
+ letter_widths
[font
][code
] > width
) break;
316 for (int t
= DC_LETTER_TEX_LENGTH
; t
--; )
317 for (int s
= DC_LETTER_TEX_LENGTH
; s
--; ) {
318 if (cursor
+ s
>= width
) continue;
320 float alpha
= letter_textures
[font
][code
][t
* DC_LETTER_TEX_LENGTH
321 + s
] * (1.0f
/ 255.0f
);
322 for (int c
= 3; c
--; ) {
323 float color
= colors
[base_color
][c
] + (1.0f
- colors
[base_color
][c
])
324 * (DC_LETTER_TEX_LENGTH
- t
+ (s
>= letter_widths
[font
][code
]
325 ? DC_LETTER_TEX_LENGTH
: s
+ (DC_LETTER_TEX_LENGTH
326 - letter_widths
[font
][code
])))
327 * (0.5f
/ (float) DC_LETTER_TEX_LENGTH
);
328 float result
= (255.0f
* color
* alpha
)
329 + texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
];
330 if (result
>= 255.0f
)
331 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
] = (GLubyte
) 255;
333 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
]
339 for (int t
= DC_LETTER_TEX_LENGTH
; t
--; )
340 for (int s
= DC_LETTER_TEX_LENGTH
; s
--; ) {
341 if (cursor
+ s
>= width
)
343 if (letter_textures
[font
][code
][t
* DC_LETTER_TEX_LENGTH
+ s
] == 0)
346 int old_alpha
= texture
[(t
* texture_width
+ cursor
+ s
) * 4 + 3];
347 int new_alpha
= letter_textures
[font
][code
][t
* DC_LETTER_TEX_LENGTH
349 if (new_alpha
+ old_alpha
>= 255)
350 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + 3] = 255;
352 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + 3]
353 = (GLubyte
) (new_alpha
+ old_alpha
);
355 for (int c
= 3; c
--; ) {
356 float color
= colors
[base_color
][c
] + (1.0f
- colors
[base_color
][c
])
357 * (DC_LETTER_TEX_LENGTH
- t
+ (s
>= letter_widths
[font
][code
]
358 ? DC_LETTER_TEX_LENGTH
: s
+ (DC_LETTER_TEX_LENGTH
359 - letter_widths
[font
][code
])))
360 * (0.5f
/ (float) DC_LETTER_TEX_LENGTH
);
361 float result
= (255.0f
* color
) + (old_alpha
* (1.0f
/ 255.0f
))
362 * texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
];
363 if (result
>= 255.0f
)
364 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
] = 255;
366 texture
[(t
* texture_width
+ cursor
+ s
) * 4 + c
]
371 cursor
+= letter_widths
[font
][code
];