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