X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=gfx%2Ftext.c;h=95478343293e5ab6a4801e94abb59c08a1e91133;hb=0c154bc0927a32f77467f32aac3cc3507baa97ca;hp=084e9511f9b84495bbf20010d3eeba1514efbe9c;hpb=41ee2287b2f2d7ec3e73e998b06076888608ed72;p=bertos.git diff --git a/gfx/text.c b/gfx/text.c index 084e9511..95478343 100755 --- a/gfx/text.c +++ b/gfx/text.c @@ -1,7 +1,7 @@ /*! * \file * @@ -15,6 +15,21 @@ /*#* *#* $Log$ + *#* Revision 1.6 2006/03/13 02:05:54 bernie + *#* Mark slow paths as UNLIKELY. + *#* + *#* Revision 1.5 2006/03/07 22:18:04 bernie + *#* Correctly compute text width for prop fonts; Make styles a per-bitmap attribute. + *#* + *#* Revision 1.4 2006/02/15 09:10:15 bernie + *#* Implement prop fonts; Fix algo styles. + *#* + *#* Revision 1.3 2006/02/10 12:31:55 bernie + *#* Add multiple font support in bitmaps. + *#* + *#* Revision 1.2 2005/11/04 18:17:45 bernie + *#* Fix header guards and includes for new location of gfx module. + *#* *#* Revision 1.1 2005/11/04 18:11:35 bernie *#* Move graphics stuff from mware/ to gfx/. *#* @@ -73,23 +88,16 @@ *#* documentation fixes *#*/ -#include "gfx.h" -#include "font.h" -#include "text.h" +#include +#include +#include +#include + +#include // FIXME: BM_DRAWPIXEL #include -/*! - * Flags degli stili algoritmici - * - * La routine di rendering del testo e' in grado di applicare - * delle semplici trasformazioni al font interno per generare - * automaticamente degli stili predefiniti (bold, italic, - * underline) a partire dal set di caratteri plain. - */ -static uint8_t text_styles; - /*! ANSI escape sequences flag: true for ESC state on */ static bool ansi_mode = false; @@ -101,12 +109,12 @@ static bool ansi_mode = false; void text_moveto(struct Bitmap *bm, int row, int col) { ASSERT(col >= 0); - ASSERT(col < bm->width / FONT_WIDTH); + ASSERT(col < bm->width / bm->font->width); ASSERT(row >= 0); - ASSERT(row < bm->height / FONT_HEIGHT); + ASSERT(row < bm->height / bm->font->height); - bm->penX = col * FONT_WIDTH; - bm->penY = row * FONT_HEIGHT; + bm->penX = col * bm->font->width; + bm->penY = row * bm->font->height; } @@ -121,92 +129,126 @@ void text_setcoord(struct Bitmap *bm, int x, int y) /*! - * Render char \a c on Bitmap \a bm + * Render char \a c on Bitmap \a bm. */ static int text_putglyph(char c, struct Bitmap *bm) { const uint8_t * PROGMEM glyph; /* font is in progmem */ - uint8_t glyph_width; - uint8_t i; - uint8_t *buf; - - /* - * Il carattere da stampare viene usato come indice per prelevare - * la prima colonna di dots del glyph all'interno del font. - */ - glyph = font + (((unsigned char)c) * FONT_WIDTH); - glyph_width = FONT_WIDTH; + uint8_t glyph_width, glyph_height, glyph_height_bytes; + unsigned char index = (unsigned char)c; - if (text_styles & STYLEF_CONDENSED) - --glyph_width; + /* Check for out of range char and replace with '?' or first char in font. */ + if (UNLIKELY(!FONT_HAS_GLYPH(bm->font, index))) + { + kprintf("Illegal char '%c' (0x%02x)\n", index, index); + if (FONT_HAS_GLYPH(bm->font, '?')) + index = '?'; + else + index = bm->font->first; + } - if (text_styles & STYLEF_EXPANDED) - glyph_width *= 2; + /* Make character relative to font start */ + index -= bm->font->first; - /* The y coord is rounded at multiples of 8 for simplicity */ - bm->penY &= ~((coord_t)7); + glyph_height = bm->font->height; + // FIXME: for vertical fonts only + glyph_height_bytes = (glyph_height + 7) / 8; - /* Check if glyph to write fits in the bitmap */ - if ((bm->penX < 0) || (bm->penX + glyph_width > bm->width) || - (bm->penY < 0) || (bm->penY + FONT_HEIGHT > bm->height)) + if (bm->font->offset) { - DB(kprintf("bad coords x=%d y=%d\n", bm->penX, bm->penY);) - return 0; + /* Proportional font */ + glyph_width = bm->font->widths[index]; /* TODO: optimize away */ + glyph = bm->font->glyph + bm->font->offset[index]; + } + else + { + /* + * Fixed-width font: compute the first column of pixels + * of the selected glyph using the character code to index + * the glyph array. + */ + glyph_width = bm->font->width; + + //For horizontal fonts + //glyph = bm->font->glyph + index * (((glyph_width + 7) / 8) * glyph_height); + glyph = bm->font->glyph + index * glyph_height_bytes * glyph_width; } - /* Locate position where to write in the raster */ - buf = bm->raster + bm->penY / 8 * bm->width + bm->penX; - - bm->penX += glyph_width; - - /* If some styles are set */ - if (text_styles) + /* Slow path for styled glyphs */ + if (UNLIKELY(bm->styles)) { - uint8_t prev_dots = 0, italic_prev_dots = 0, new_dots; + uint8_t prev_dots = 0, italic_prev_dots = 0; uint8_t dots; + uint8_t row, col; - /* Per ogni colonna di dot del glyph... */ - for (i = 0; i < glyph_width; ++i) - { - dots = PGM_READ_CHAR(glyph); + /* This style alone could be handled by the fast path too */ + if (bm->styles & STYLEF_CONDENSED) + --glyph_width; - /* Advance to next column in glyph. - * Expand: advances only once every two columns - */ - if (!(text_styles & STYLEF_EXPANDED) || (i & 1)) - glyph++; + if (bm->styles & STYLEF_EXPANDED) + glyph_width *= 2; - /* Italic: get lower 4 dots from previous column */ - if (text_styles & STYLEF_ITALIC) - { - new_dots = dots; - dots = (dots & 0xF0) | italic_prev_dots; - italic_prev_dots = new_dots & 0x0F; - } + /* Check if glyph fits in the bitmap. */ + if ((bm->penX < 0) || (bm->penX + glyph_width > bm->width) + || (bm->penY < 0) || (bm->penY + glyph_height > bm->height)) + { + kprintf("bad coords x=%d y=%d\n", bm->penX, bm->penY); + return 0; + } - /* Bold: "or" pixels with the previous column */ - if (text_styles & STYLEF_BOLD) + for (row = 0; row < glyph_height_bytes; ++row) + { + /* For each dot column in the glyph... */ + for (col = 0; col < glyph_width; ++col) { - new_dots = dots; - dots |= prev_dots; - prev_dots = new_dots; + uint8_t src_col = col; + uint8_t i; + + /* Expanded style: advances only once every two columns. */ + if (bm->styles & STYLEF_EXPANDED) + src_col /= 2; + + /* Fetch a column of dots from glyph. */ + dots = PGM_READ_CHAR(glyph + src_col * glyph_height_bytes + row); + + /* Italic: get lower 4 dots from previous column */ + if (bm->styles & STYLEF_ITALIC) + { + uint8_t new_dots = dots; + dots = (dots & 0xF0) | italic_prev_dots; + italic_prev_dots = new_dots & 0x0F; + } + + /* Bold: "or" pixels with the previous column */ + if (bm->styles & STYLEF_BOLD) + { + uint8_t new_dots = dots; + dots |= prev_dots; + prev_dots = new_dots; + } + + /* Underlined: turn on base pixel */ + if (bm->styles & STYLEF_UNDERLINE) + dots |= 0x80; + + /* Inverted: invert pixels */ + if (bm->styles & STYLEF_INVERT) + dots = ~dots; + + /* Output dots */ + for (i = 0; i < 8 && (row * 8) + i < glyph_height; ++i) + BM_DRAWPIXEL(bm, bm->penX + col, bm->penY + row * 8 + i, dots & (1<penX, bm->penY, glyph, glyph_width, glyph_height, glyph_height_bytes); + } + + /* Update current pen position */ + bm->penX += glyph_width; return c; } @@ -219,7 +261,7 @@ static int text_putglyph(char c, struct Bitmap *bm) int text_putchar(char c, struct Bitmap *bm) { /* Handle ANSI escape sequences */ - if (ansi_mode) + if (UNLIKELY(ansi_mode)) { switch (c) { @@ -227,7 +269,7 @@ int text_putchar(char c, struct Bitmap *bm) gfx_bitmapClear(bm); bm->penX = 0; bm->penY = 0; - text_style(0, STYLEF_MASK); + text_style(bm, 0, STYLEF_MASK); break; DB(default: kprintf("Unknown ANSI esc code: %x\n", c);) @@ -240,9 +282,9 @@ int text_putchar(char c, struct Bitmap *bm) } else if (c == '\n') /* Go one line down on a line-feed */ { - if (bm->penY + FONT_HEIGHT < bm->height) + if (bm->penY + bm->font->height < bm->height) { - bm->penY += FONT_HEIGHT; + bm->penY += bm->font->height; bm->penX = 0; } } @@ -264,35 +306,36 @@ void text_clear(struct Bitmap *bmp) } -void text_clearLine(struct Bitmap *bmp, int line) +void text_clearLine(struct Bitmap *bm, int line) { - gfx_rectClear(bmp, 0, line * FONT_HEIGHT, bmp->width, (line + 1) * FONT_HEIGHT); + gfx_rectClear(bm, 0, line * bm->font->height, bm->width, (line + 1) * bm->font->height); } -/*! +/** * Set/clear algorithmic font style bits. * + * \param bm Pointer to Bitmap to affect. * \param flags Style flags to set * \param mask Mask of flags to modify * \return Old style flags * * Examples: * Turn on bold, leave other styles alone - * \code prt_style(STYLEF_BOLD, STYLEF_BOLD); \endcode + * \code text_style(bm, STYLEF_BOLD, STYLEF_BOLD); \endcode * * Turn off bold and turn on italic, leave others as they are - * \code prt_style(STYLEF_ITALIC, STYLEF_BOLD | STYLEF_ITALIC); \endcode + * \code text_style(bm, STYLEF_ITALIC, STYLEF_BOLD | STYLEF_ITALIC); \endcode * * Query current style without chaning it - * \code style = prt_style(0, 0); \endcode + * \code style = text_style(bm, 0, 0); \endcode * * Reset all styles (plain text) - * \code prt_style(0, STYLE_MASK); \endcode + * \code text_style(bm, 0, STYLE_MASK); \endcode */ -uint8_t text_style(uint8_t flags, uint8_t mask) +uint8_t text_style(struct Bitmap *bm, uint8_t flags, uint8_t mask) { - uint8_t old = text_styles; - text_styles = (text_styles & ~mask) | flags; + uint8_t old = bm->styles; + bm->styles = (bm->styles & ~mask) | flags; return old; }