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