text_format.c

Go to the documentation of this file.
00001 
00041 #include "text.h"
00042 
00043 #include <mware/formatwr.h> /* _formatted_write() */
00044 #include <gfx/font.h>
00045 #include <gfx/gfx.h>
00046 
00047 #include <stdio.h> /* vsprintf() */
00048 #include <stdarg.h>
00049 #include <string.h> /* strlen() */
00050 
00061 int PGM_FUNC(text_puts)(const char * PGM_ATTR str, struct Bitmap *bm)
00062 {
00063     char c;
00064 
00065     while ((c = PGM_READ_CHAR(str++)))
00066         text_putchar(c, bm);
00067 
00068     return 0;
00069 }
00070 
00071 
00082 int PGM_FUNC(text_vprintf)(struct Bitmap *bm, const char * PGM_ATTR fmt, va_list ap)
00083 {
00084     return PGM_FUNC(_formatted_write)(fmt, (void (*)(char, void *))text_putchar, bm, ap);
00085 }
00086 
00096 int PGM_FUNC(text_printf)(struct Bitmap *bm, const char * PGM_ATTR fmt, ...)
00097 {
00098     int len;
00099 
00100     va_list ap;
00101     va_start(ap, fmt);
00102     len = PGM_FUNC(text_vprintf)(bm, fmt, ap);
00103     va_end(ap);
00104 
00105     return len;
00106 }
00107 
00113 int PGM_FUNC(text_xyvprintf)(struct Bitmap *bm,
00114         coord_t x, coord_t y, uint16_t style, const char * PGM_ATTR fmt, va_list ap)
00115 {
00116     int len;
00117     uint8_t oldstyle = 0;
00118 
00119     text_setCoord(bm, x, y);
00120 
00121     if (style & STYLEF_MASK)
00122         oldstyle = text_style(bm, style, STYLEF_MASK);
00123 
00124     if (style & (TEXT_CENTER | TEXT_RIGHT))
00125     {
00126         uint8_t pad = bm->width - PGM_FUNC(text_vwidthf)(bm, fmt, ap);
00127 
00128         if (style & TEXT_CENTER)
00129             pad /= 2;
00130 
00131         if (style & TEXT_FILL)
00132             gfx_rectFillC(bm, 0, y, pad, y + bm->font->height,
00133                 (style & STYLEF_INVERT) ? 0xFF : 0x00);
00134 
00135         text_setCoord(bm, pad, y);
00136     }
00137 
00138     len = PGM_FUNC(text_vprintf)(bm, fmt, ap);
00139 
00140     if (style & TEXT_FILL)
00141         gfx_rectFillC(bm, bm->penX, y, bm->width, y + bm->font->height,
00142             (style & STYLEF_INVERT) ? 0xFF : 0x00);
00143 
00144     /* Restore old style */
00145     if (style & STYLEF_MASK)
00146         text_style(bm, oldstyle, STYLEF_MASK);
00147 
00148     return len;
00149 }
00150 
00151 
00166 int PGM_FUNC(text_xyprintf)(struct Bitmap *bm,
00167         coord_t x, coord_t y, uint16_t style, const char * PGM_ATTR fmt, ...)
00168 {
00169     int len;
00170     va_list ap;
00171 
00172     va_start(ap, fmt);
00173     len = PGM_FUNC(text_xyvprintf)(bm, x, y, style, fmt, ap);
00174     va_end(ap);
00175 
00176     return len;
00177 }
00178 
00179 
00185 int PGM_FUNC(text_xprintf)(struct Bitmap *bm,
00186         uint8_t row, uint8_t col, uint16_t style, const char * PGM_ATTR fmt, ...)
00187 {
00188     int len;
00189     va_list ap;
00190 
00191     va_start(ap, fmt);
00192     len = PGM_FUNC(text_xyvprintf)(
00193             bm, col * bm->font->width, row * bm->font->height,
00194             style, fmt, ap);
00195     va_end(ap);
00196 
00197     return len;
00198 }
00199 
00200 
00201 struct TextWidthData
00202 {
00203     Bitmap *bitmap;
00204     coord_t width;
00205 };
00206 
00219 static int text_charWidth(int c, struct TextWidthData *twd)
00220 {
00221     unsigned char index = (unsigned char)c;
00222     Bitmap *bm = twd->bitmap;
00223     coord_t glyph_width;
00224 
00225 
00226     if (UNLIKELY(!FONT_HAS_GLYPH(bm->font, index)))
00227     {
00228         if (!FONT_HAS_GLYPH(bm->font, '?'))
00229             index = '?';
00230         else
00231             index = bm->font->first;
00232     }
00233 
00234     /* Make character relative to font start */
00235     index -= bm->font->first;
00236 
00237     if (bm->font->offset)
00238         /* Proportional font */
00239         glyph_width = bm->font->widths[index]; /* TODO: optimize away */
00240     else
00241         /* Fixed width font */
00242         glyph_width = bm->font->width;
00243 
00244     if (bm->styles & STYLEF_CONDENSED)
00245         --glyph_width;
00246 
00247     if (bm->styles & STYLEF_EXPANDED)
00248         glyph_width *= 2;
00249 
00250     twd->width += glyph_width;
00251 
00252     return c;
00253 }
00254 
00258 int PGM_FUNC(text_vwidthf)(
00259     UNUSED_ARG(struct Bitmap *, bm),
00260     const char * PGM_ATTR fmt,
00261     va_list ap)
00262 {
00263     /* Fixed font with no styles affecting the width? */
00264     if (!bm->font->offset && !(bm->styles & (STYLEF_CONDENSED | STYLEF_EXPANDED)))
00265         return PGM_FUNC(vsprintf)(NULL, fmt, ap) * bm->font->width;
00266     else
00267     {
00268         struct TextWidthData twd;
00269         twd.bitmap = bm;
00270         twd.width = 0;
00271         _formatted_write(fmt, (void (*)(char, void *))text_charWidth, &twd, ap);
00272         return twd.width;
00273     }
00274 }
00275 
00276 
00280 int PGM_FUNC(text_widthf)(struct Bitmap *bm, const char * PGM_ATTR fmt, ...)
00281 {
00282     int width;
00283 
00284     va_list ap;
00285     va_start(ap, fmt);
00286     width = PGM_FUNC(text_vwidthf)(bm, fmt, ap);
00287     va_end(ap);
00288 
00289     return width;
00290 }