1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Text drawing routines.
12 *
13 * By Shawn Hargreaves.
14 *
15 * textout_justify() by Seymour Shlien.
16 *
17 * Laurence Withers added the textout_ex() function family.
18 *
19 * See readme.txt for copyright information.
20 */
21
22
23 #include "allegro.h"
24 #include "allegro/internal/aintern.h"
25
26
27
28 /* textout_ex:
29 * Writes the null terminated string str onto bmp at position x, y, using
30 * the specified font, foreground color and background color (-1 is trans).
31 * If color is -1 and a proportional font is in use, it will be drawn
32 * using the colors from the original font bitmap (the one imported into
33 * the grabber program), which allows multicolored text output.
34 */
textout_ex(BITMAP * bmp,AL_CONST FONT * f,AL_CONST char * str,int x,int y,int color,int bg)35 void textout_ex(BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color, int bg)
36 {
37 ASSERT(bmp);
38 ASSERT(f);
39 ASSERT(str);
40 f->vtable->render(f, str, color, bg, bmp, x, y);
41 }
42
43
44
45 /* textout_centre_ex:
46 * Like textout_ex(), but uses the x coordinate as the centre rather than
47 * the left of the string.
48 */
textout_centre_ex(BITMAP * bmp,AL_CONST FONT * f,AL_CONST char * str,int x,int y,int color,int bg)49 void textout_centre_ex(BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color, int bg)
50 {
51 int len;
52 ASSERT(bmp);
53 ASSERT(f);
54 ASSERT(str);
55
56 len = text_length(f, str);
57 f->vtable->render(f, str, color, bg, bmp, x - len/2, y);
58 }
59
60
61
62 /* textout_right_ex:
63 * Like textout_ex(), but uses the x coordinate as the right rather than
64 * the left of the string.
65 */
textout_right_ex(BITMAP * bmp,AL_CONST FONT * f,AL_CONST char * str,int x,int y,int color,int bg)66 void textout_right_ex(BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color, int bg)
67 {
68 int len;
69 ASSERT(bmp);
70 ASSERT(f);
71 ASSERT(str);
72
73 len = text_length(f, str);
74 f->vtable->render(f, str, color, bg, bmp, x - len, y);
75 }
76
77
78
79 /* textout_justify_ex:
80 * Like textout_ex(), but justifies the string to the specified area.
81 */
82 #define MAX_TOKEN 128
83
textout_justify_ex(BITMAP * bmp,AL_CONST FONT * f,AL_CONST char * str,int x1,int x2,int y,int diff,int color,int bg)84 void textout_justify_ex(BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x1, int x2, int y, int diff, int color, int bg)
85 {
86 char toks[32];
87 char *tok[MAX_TOKEN];
88 char *strbuf, *strlast;
89 int i, minlen, last, space;
90 float fleft, finc;
91 ASSERT(bmp);
92 ASSERT(f);
93 ASSERT(str);
94
95 i = usetc(toks, ' ');
96 i += usetc(toks+i, '\t');
97 i += usetc(toks+i, '\n');
98 i += usetc(toks+i, '\r');
99 usetc(toks+i, 0);
100
101 /* count words and measure min length (without spaces) */
102 strbuf = _al_ustrdup(str);
103 if (!strbuf) {
104 /* Can't justify ! */
105 f->vtable->render(f, str, color, bg, bmp, x1, y);
106 return;
107 }
108
109 minlen = 0;
110 last = 0;
111 tok[last] = ustrtok_r(strbuf, toks, &strlast);
112
113 while (tok[last]) {
114 minlen += text_length(f, tok[last]);
115 if (++last == MAX_TOKEN)
116 break;
117 tok[last] = ustrtok_r(NULL, toks, &strlast);
118 }
119
120 /* amount of room for space between words */
121 space = x2 - x1 - minlen;
122
123 if ((space <= 0) || (space > diff) || (last < 2)) {
124 /* can't justify */
125 _AL_FREE(strbuf);
126 f->vtable->render(f, str, color, bg, bmp, x1, y);
127 return;
128 }
129
130 /* distribute space left evenly between words */
131 fleft = (float)x1;
132 finc = (float)space / (float)(last-1);
133 for (i=0; i<last; i++) {
134 f->vtable->render(f, tok[i], color, bg, bmp, (int)fleft, y);
135 fleft += (float)text_length(f, tok[i]) + finc;
136 }
137
138 _AL_FREE(strbuf);
139 }
140
141
142
143 /* textprintf_ex:
144 * Formatted text output, using a printf() style format string.
145 */
textprintf_ex(BITMAP * bmp,AL_CONST FONT * f,int x,int y,int color,int bg,AL_CONST char * format,...)146 void textprintf_ex(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...)
147 {
148 char buf[512];
149 va_list ap;
150 ASSERT(bmp);
151 ASSERT(f);
152 ASSERT(format);
153
154 va_start(ap, format);
155 uvszprintf(buf, sizeof(buf), format, ap);
156 va_end(ap);
157
158 textout_ex(bmp, f, buf, x, y, color, bg);
159 }
160
161
162
163 /* textprintf_centre_ex:
164 * Like textprintf_ex(), but uses the x coordinate as the centre rather than
165 * the left of the string.
166 */
textprintf_centre_ex(BITMAP * bmp,AL_CONST FONT * f,int x,int y,int color,int bg,AL_CONST char * format,...)167 void textprintf_centre_ex(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...)
168 {
169 char buf[512];
170 va_list ap;
171 ASSERT(bmp);
172 ASSERT(f);
173 ASSERT(format);
174
175 va_start(ap, format);
176 uvszprintf(buf, sizeof(buf), format, ap);
177 va_end(ap);
178
179 textout_centre_ex(bmp, f, buf, x, y, color, bg);
180 }
181
182
183
184 /* textprintf_right_ex:
185 * Like textprintf_ex(), but uses the x coordinate as the right rather than
186 * the left of the string.
187 */
textprintf_right_ex(BITMAP * bmp,AL_CONST FONT * f,int x,int y,int color,int bg,AL_CONST char * format,...)188 void textprintf_right_ex(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...)
189 {
190 char buf[512];
191 va_list ap;
192 ASSERT(bmp);
193 ASSERT(f);
194 ASSERT(format);
195
196 va_start(ap, format);
197 uvszprintf(buf, sizeof(buf), format, ap);
198 va_end(ap);
199
200 textout_right_ex(bmp, f, buf, x, y, color, bg);
201 }
202
203
204
205 /* textprintf_justify_ex:
206 * Like textprintf_ex(), but right justifies the string to the specified area.
207 */
textprintf_justify_ex(BITMAP * bmp,AL_CONST FONT * f,int x1,int x2,int y,int diff,int color,int bg,AL_CONST char * format,...)208 void textprintf_justify_ex(BITMAP *bmp, AL_CONST FONT *f, int x1, int x2, int y, int diff, int color, int bg, AL_CONST char *format, ...)
209 {
210 char buf[512];
211 va_list ap;
212 ASSERT(bmp);
213 ASSERT(f);
214 ASSERT(format);
215
216 va_start(ap, format);
217 uvszprintf(buf, sizeof(buf), format, ap);
218 va_end(ap);
219
220 textout_justify_ex(bmp, f, buf, x1, x2, y, diff, color, bg);
221 }
222
223
224
225 /* text_length:
226 * Calculates the length of a string in a particular font.
227 */
text_length(AL_CONST FONT * f,AL_CONST char * str)228 int text_length(AL_CONST FONT *f, AL_CONST char *str)
229 {
230 ASSERT(f);
231 ASSERT(str);
232 return f->vtable->text_length(f, str);
233 }
234
235
236
237 /* text_height:
238 * Returns the height of a character in the specified font.
239 */
text_height(AL_CONST FONT * f)240 int text_height(AL_CONST FONT *f)
241 {
242 ASSERT(f);
243 return f->vtable->font_height(f);
244 }
245
246
247
248 /* destroy_font:
249 * Frees the memory being used by a font structure.
250 * This is now wholly handled in the vtable.
251 */
destroy_font(FONT * f)252 void destroy_font(FONT *f)
253 {
254 ASSERT(f);
255 f->vtable->destroy(f);
256 }
257
258
259
260 /* The following code has been deprecated, as it relies on a global
261 * variable. This is no good in multithreaded code, and using a bg
262 * parameter also simplifies other code (for instance, the GUI).
263 */
264
265 int _textmode = 0;
266
267
268
269 /* text_mode:
270 * Sets the mode in which text will be drawn. If mode is positive, text
271 * output will be opaque and the background will be set to mode. If mode
272 * is negative, text will be drawn transparently (ie. the background will
273 * not be altered). The default is a mode of zero.
274 * Returns previous mode.
275 */
text_mode(int mode)276 int text_mode(int mode)
277 {
278 int old_mode = _textmode;
279
280 if (mode < 0)
281 _textmode = -1;
282 else
283 _textmode = mode;
284
285 return old_mode;
286 }
287
288
289
290 /* textout: (inlined)
291 * Writes the null terminated string str onto bmp at position x, y, using
292 * the current text mode and the specified font and foreground color.
293 * If color is -1 and a proportional font is in use, it will be drawn
294 * using the colors from the original font bitmap (the one imported into
295 * the grabber program), which allows multicolored text output.
296 */
297
298
299
300 /* textout_centre: (inlined)
301 * Like textout(), but uses the x coordinate as the centre rather than
302 * the left of the string.
303 */
304
305
306
307 /* textout_right: (inlined)
308 * Like textout(), but uses the x coordinate as the right rather than
309 * the left of the string.
310 */
311
312
313
314 /* textout_justify: (inlined)
315 * Like textout(), but justifies the string to the specified area.
316 */
317
318
319
320 /* textprintf:
321 * Formatted text output, using a printf() style format string.
322 */
textprintf(BITMAP * bmp,AL_CONST FONT * f,int x,int y,int color,AL_CONST char * format,...)323 void textprintf(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...)
324 {
325 char buf[512];
326 va_list ap;
327 ASSERT(bmp);
328 ASSERT(f);
329 ASSERT(format);
330
331 va_start(ap, format);
332 uvszprintf(buf, sizeof(buf), format, ap);
333 va_end(ap);
334
335 textout_ex(bmp, f, buf, x, y, color, _textmode);
336 }
337
338
339
340 /* textprintf_centre:
341 * Like textprintf(), but uses the x coordinate as the centre rather than
342 * the left of the string.
343 */
textprintf_centre(BITMAP * bmp,AL_CONST FONT * f,int x,int y,int color,AL_CONST char * format,...)344 void textprintf_centre(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...)
345 {
346 char buf[512];
347 va_list ap;
348 ASSERT(bmp);
349 ASSERT(f);
350 ASSERT(format);
351
352 va_start(ap, format);
353 uvszprintf(buf, sizeof(buf), format, ap);
354 va_end(ap);
355
356 textout_centre_ex(bmp, f, buf, x, y, color, _textmode);
357 }
358
359
360
361 /* textprintf_right:
362 * Like textout(), but uses the x coordinate as the right rather than
363 * the left of the string.
364 */
textprintf_right(BITMAP * bmp,AL_CONST FONT * f,int x,int y,int color,AL_CONST char * format,...)365 void textprintf_right(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...)
366 {
367 char buf[512];
368 va_list ap;
369 ASSERT(bmp);
370 ASSERT(f);
371 ASSERT(format);
372
373 va_start(ap, format);
374 uvszprintf(buf, sizeof(buf), format, ap);
375 va_end(ap);
376
377 textout_right_ex(bmp, f, buf, x, y, color, _textmode);
378 }
379
380
381
382 /* textprintf_justify:
383 * Like textprintf(), but right justifies the string to the specified area.
384 */
textprintf_justify(BITMAP * bmp,AL_CONST FONT * f,int x1,int x2,int y,int diff,int color,AL_CONST char * format,...)385 void textprintf_justify(BITMAP *bmp, AL_CONST FONT *f, int x1, int x2, int y, int diff, int color, AL_CONST char *format, ...)
386 {
387 char buf[512];
388 va_list ap;
389 ASSERT(bmp);
390 ASSERT(f);
391 ASSERT(format);
392
393 va_start(ap, format);
394 uvszprintf(buf, sizeof(buf), format, ap);
395 va_end(ap);
396
397 textout_justify_ex(bmp, f, buf, x1, x2, y, diff, color, _textmode);
398 }
399