Rename myself
[bertos.git] / bertos / gfx / text_format.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 1999 Bernie Innocenti <bernie@codewiz.org>
31  *
32  * -->
33  *
34  * \brief printf-family routines for text output
35  *
36  * \version $Id$
37  * \author Bernie Innocenti <bernie@codewiz.org>
38  * \author Stefano Fedrigo <aleph@develer.com>
39  */
40
41 /*#*
42  *#* $Log$
43  *#* Revision 1.10  2006/07/19 12:56:26  bernie
44  *#* Convert to new Doxygen style.
45  *#*
46  *#* Revision 1.9  2006/04/27 05:39:24  bernie
47  *#* Enhance text rendering to arbitrary x,y coords.
48  *#*
49  *#* Revision 1.8  2006/03/22 09:50:11  bernie
50  *#* Don't use C99 stuff.
51  *#*
52  *#* Revision 1.7  2006/03/20 17:51:55  bernie
53  *#* Cleanups.
54  *#*
55  *#* Revision 1.6  2006/03/13 02:05:54  bernie
56  *#* Mark slow paths as UNLIKELY.
57  *#*
58  *#* Revision 1.5  2006/03/07 22:18:04  bernie
59  *#* Correctly compute text width for prop fonts; Make styles a per-bitmap attribute.
60  *#*
61  *#* Revision 1.4  2006/02/10 12:31:33  bernie
62  *#* Add multiple font support in bitmaps.
63  *#*
64  *#* Revision 1.3  2005/11/27 23:31:58  bernie
65  *#* Reorder includes.
66  *#*
67  *#* Revision 1.2  2005/11/04 18:17:45  bernie
68  *#* Fix header guards and includes for new location of gfx module.
69  *#*
70  *#* Revision 1.1  2005/11/04 18:11:35  bernie
71  *#* Move graphics stuff from mware/ to gfx/.
72  *#*
73  *#* Revision 1.10  2005/11/04 16:20:02  bernie
74  *#* Fix reference to README.devlib in header.
75  *#*
76  *#* Revision 1.9  2004/12/31 17:47:45  bernie
77  *#* Rename UNUSED() to UNUSED_ARG().
78  *#*
79  *#* Revision 1.8  2004/11/16 21:16:56  bernie
80  *#* Update to new naming scheme in mware/gfx.c.
81  *#*
82  *#* Revision 1.7  2004/10/03 19:05:04  bernie
83  *#* text_widthf(), text_vwidthf(): New functions.
84  *#*
85  *#* Revision 1.6  2004/09/14 20:59:04  bernie
86  *#* text_xprintf(): Support all styles; Pixel-wise text centering.
87  *#*
88  *#* Revision 1.5  2004/08/25 14:12:09  rasky
89  *#* Aggiornato il comment block dei log RCS
90  *#*
91  *#* Revision 1.4  2004/08/05 18:46:44  bernie
92  *#* Documentation improvements.
93  *#*
94  *#* Revision 1.3  2004/08/03 15:57:18  aleph
95  *#* Add include to fix warning for vsprintf()
96  *#*
97  *#* Revision 1.2  2004/06/03 11:27:09  bernie
98  *#* Add dual-license information.
99  *#*
100  *#* Revision 1.1  2004/05/23 15:43:16  bernie
101  *#* Import mware modules.
102  *#*
103  *#* Revision 1.2  2004/03/26 18:50:50  bernie
104  *#* Move _PROGMEM stuff to compiler.h
105  *#*
106  *#* Revision 1.1  2004/03/19 16:52:28  bernie
107  *#* Move printf() like functions from text.c to text_format.c and add PROGMEM versions.
108  *#*
109  *#*/
110
111 #include "text.h"
112
113 #include <mware/formatwr.h> /* _formatted_write() */
114 #include <gfx/font.h>
115 #include <gfx/gfx.h>
116
117 #include <stdio.h> /* vsprintf() */
118 #include <stdarg.h>
119 #include <string.h> /* strlen() */
120
121 /**
122  * Render string \a str in Bitmap \a bm at current cursor position
123  *
124  * \note Text formatting functions are also available with an _P suffix
125  *       accepting the source string from program memory.  This feature
126  *       is only available (and useful) on Harvard microprocessors such
127  *       as the AVR.
128  *
129  * \see text_putchar()
130  */
131 int PGM_FUNC(text_puts)(const char * PGM_ATTR str, struct Bitmap *bm)
132 {
133         char c;
134
135         while ((c = PGM_READ_CHAR(str++)))
136                 text_putchar(c, bm);
137
138         return 0;
139 }
140
141
142 /**
143  * vprintf()-like formatter to render text in a Bitmap.
144  *
145  * Perform vprintf()-like formatting on the \a fmt format string using the
146  * variable-argument list \a ap.
147  * Render the resulting string in Bitmap \a bm starting at the current
148  * cursor position.
149  *
150  * \see text_puts() text_putchar() text_printf()
151  */
152 int PGM_FUNC(text_vprintf)(struct Bitmap *bm, const char * PGM_ATTR fmt, va_list ap)
153 {
154         return PGM_FUNC(_formatted_write)(fmt, (void (*)(char, void *))text_putchar, bm, ap);
155 }
156
157 /**
158  * printf()-like formatter to render text in a Bitmap.
159  *
160  * Perform printf()-like formatting on the \a fmt format string.
161  * Render the resulting string in Bitmap \a bm starting at the
162  * current cursor position.
163  *
164  * \see text_puts() text_putchar() text_vprintf()
165  */
166 int PGM_FUNC(text_printf)(struct Bitmap *bm, const char * PGM_ATTR fmt, ...)
167 {
168         int len;
169
170         va_list ap;
171         va_start(ap, fmt);
172         len = PGM_FUNC(text_vprintf)(bm, fmt, ap);
173         va_end(ap);
174
175         return len;
176 }
177
178 /**
179  * Render text with vprintf()-like formatting at a specified pixel position.
180  *
181  * \see text_xyprintf()
182  */
183 int PGM_FUNC(text_xyvprintf)(struct Bitmap *bm,
184                 coord_t x, coord_t y, uint16_t style, const char * PGM_ATTR fmt, va_list ap)
185 {
186         int len;
187         uint8_t oldstyle = 0;
188
189         text_setCoord(bm, x, y);
190
191         if (style & STYLEF_MASK)
192                 oldstyle = text_style(bm, style, STYLEF_MASK);
193
194         if (style & (TEXT_CENTER | TEXT_RIGHT))
195         {
196                 uint8_t pad = bm->width - PGM_FUNC(text_vwidthf)(bm, fmt, ap);
197
198                 if (style & TEXT_CENTER)
199                         pad /= 2;
200
201                 if (style & TEXT_FILL)
202                         gfx_rectFillC(bm, 0, y, pad, y + bm->font->height,
203                                 (style & STYLEF_INVERT) ? 0xFF : 0x00);
204
205                 text_setCoord(bm, pad, y);
206         }
207
208         len = PGM_FUNC(text_vprintf)(bm, fmt, ap);
209
210         if (style & TEXT_FILL)
211                 gfx_rectFillC(bm, bm->penX, y, bm->width, y + bm->font->height,
212                         (style & STYLEF_INVERT) ? 0xFF : 0x00);
213
214         /* Restore old style */
215         if (style & STYLEF_MASK)
216                 text_style(bm, oldstyle, STYLEF_MASK);
217
218         return len;
219 }
220
221
222 /**
223  * Render text with printf()-like formatting at a specified pixel position.
224  *
225  * \param bm Bitmap where to render the text
226  * \param x     [pixels] Initial X coordinate of text.
227  * \param y     [pixels] Coordinate of top border of text.
228  * \param style Formatting style to use.  In addition to any STYLEF_
229  *        flag, it can be TEXT_NORMAL, TEXT_FILL, TEXT_INVERT or
230  *        TEXT_RIGHT, or a combination of these flags ORed together.
231  * \param fmt  String possibly containing printf() formatting commands.
232  *
233  * \see text_puts() text_putchar() text_printf() text_vprintf()
234  * \see text_moveTo() text_style()
235  */
236 int PGM_FUNC(text_xyprintf)(struct Bitmap *bm,
237                 coord_t x, coord_t y, uint16_t style, const char * PGM_ATTR fmt, ...)
238 {
239         int len;
240         va_list ap;
241
242         va_start(ap, fmt);
243         len = PGM_FUNC(text_xyvprintf)(bm, x, y, style, fmt, ap);
244         va_end(ap);
245
246         return len;
247 }
248
249
250 /**
251  * Render text with printf()-like formatting at a specified row/column position.
252  *
253  * \see text_xyprintf()
254  */
255 int PGM_FUNC(text_xprintf)(struct Bitmap *bm,
256                 uint8_t row, uint8_t col, uint16_t style, const char * PGM_ATTR fmt, ...)
257 {
258         int len;
259         va_list ap;
260
261         va_start(ap, fmt);
262         len = PGM_FUNC(text_xyvprintf)(
263                         bm, col * bm->font->width, row * bm->font->height,
264                         style, fmt, ap);
265         va_end(ap);
266
267         return len;
268 }
269
270
271 struct TextWidthData
272 {
273         Bitmap *bitmap;
274         coord_t width;
275 };
276
277 /**
278  * Compute width in pixels of a character.
279  *
280  * Compute the on screen width of a character, taking the
281  * current style and font into account.
282  *
283  * The width is accumulated in the WidthData structure
284  * passed as second argument.
285  *
286  * This is a formatted_write() callback used by text_vwidthf()
287  * to compute the length of a formatted string.
288  */
289 static int text_charWidth(int c, struct TextWidthData *twd)
290 {
291         unsigned char index = (unsigned char)c;
292         Bitmap *bm = twd->bitmap;
293         coord_t glyph_width;
294
295
296         if (UNLIKELY(!FONT_HAS_GLYPH(bm->font, index)))
297         {
298                 if (!FONT_HAS_GLYPH(bm->font, '?'))
299                         index = '?';
300                 else
301                         index = bm->font->first;
302         }
303
304         /* Make character relative to font start */
305         index -= bm->font->first;
306
307         if (bm->font->offset)
308                 /* Proportional font */
309                 glyph_width = bm->font->widths[index]; /* TODO: optimize away */
310         else
311                 /* Fixed width font */
312                 glyph_width = bm->font->width;
313
314         if (bm->styles & STYLEF_CONDENSED)
315                 --glyph_width;
316
317         if (bm->styles & STYLEF_EXPANDED)
318                 glyph_width *= 2;
319
320         twd->width += glyph_width;
321
322         return c;
323 }
324
325 /**
326  * Return the width in pixels of a vprintf()-formatted string.
327  */
328 int PGM_FUNC(text_vwidthf)(
329         UNUSED_ARG(struct Bitmap *, bm),
330         const char * PGM_ATTR fmt,
331         va_list ap)
332 {
333         /* Fixed font with no styles affecting the width? */
334         if (!bm->font->offset && !(bm->styles & (STYLEF_CONDENSED | STYLEF_EXPANDED)))
335                 return PGM_FUNC(vsprintf)(NULL, fmt, ap) * bm->font->width;
336         else
337         {
338                 struct TextWidthData twd;
339                 twd.bitmap = bm;
340                 twd.width = 0;
341                 _formatted_write(fmt, (void (*)(char, void *))text_charWidth, &twd, ap);
342                 return twd.width;
343         }
344 }
345
346
347 /**
348  * Return the width in pixels of a printf()-formatted string.
349  */
350 int PGM_FUNC(text_widthf)(struct Bitmap *bm, const char * PGM_ATTR fmt, ...)
351 {
352         int width;
353
354         va_list ap;
355         va_start(ap, fmt);
356         width = PGM_FUNC(text_vwidthf)(bm, fmt, ap);
357         va_end(ap);
358
359         return width;
360 }