From 44ef4ac25b39789e6857ffb37b171ec1dc18d910 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Wed, 18 Sep 2024 03:50:46 +0200 Subject: [PATCH] gdisp: Update font decoder --- src/gdisp/mcufont/mf_bwfont.c | 24 +++---- src/gdisp/mcufont/mf_config.h | 7 +- src/gdisp/mcufont/mf_encoding.c | 14 ++-- src/gdisp/mcufont/mf_encoding.h | 4 +- src/gdisp/mcufont/mf_font.c | 80 ++++++++++++++++------- src/gdisp/mcufont/mf_font.h | 27 ++++++-- src/gdisp/mcufont/mf_justify.c | 61 +++++++++-------- src/gdisp/mcufont/mf_kerning.c | 26 ++++---- src/gdisp/mcufont/mf_kerning.h | 6 +- src/gdisp/mcufont/mf_rlefont.c | 105 +++++++++++++++--------------- src/gdisp/mcufont/mf_rlefont.h | 2 +- src/gdisp/mcufont/mf_scaledfont.c | 28 ++++---- src/gdisp/mcufont/mf_scaledfont.h | 18 +---- src/gdisp/mcufont/mf_wordwrap.c | 9 +-- src/gdisp/mcufont/mf_wordwrap.h | 6 +- 15 files changed, 232 insertions(+), 185 deletions(-) diff --git a/src/gdisp/mcufont/mf_bwfont.c b/src/gdisp/mcufont/mf_bwfont.c index b2b17a21..87f34e6a 100644 --- a/src/gdisp/mcufont/mf_bwfont.c +++ b/src/gdisp/mcufont/mf_bwfont.c @@ -27,7 +27,7 @@ static const struct mf_bwfont_char_range_s *find_char_range( return range; } } - + return 0; } @@ -53,7 +53,7 @@ static gU8 render_char(const struct mf_bwfont_char_range_s *r, gU8 x, y, height, num_cols; gU8 bit, byte, mask; bool oldstate, newstate; - + if (r->width) { data = r->glyph_data + r->width * index * r->height_bytes; @@ -64,18 +64,18 @@ static gU8 render_char(const struct mf_bwfont_char_range_s *r, data = r->glyph_data + r->glyph_offsets[index] * r->height_bytes; num_cols = r->glyph_offsets[index + 1] - r->glyph_offsets[index]; } - + stride = r->height_bytes; height = r->height_pixels; y0 += r->offset_y; x0 += r->offset_x; bit = 0; byte = 0; - + for (y = 0; y < height; y++) { mask = (1 << bit); - + oldstate = false; runlen = 0; p = data + byte; @@ -88,19 +88,19 @@ static gU8 render_char(const struct mf_bwfont_char_range_s *r, { callback(x0 + x - runlen, y0 + y, runlen, 255, state); } - + oldstate = newstate; runlen = 0; } - + runlen++; } - + if (oldstate && runlen) { callback(x0 + x - runlen, y0 + y, runlen, 255, state); } - + bit++; if (bit > 7) { @@ -108,7 +108,7 @@ static gU8 render_char(const struct mf_bwfont_char_range_s *r, byte++; } } - + return get_width(r, index); } @@ -125,7 +125,7 @@ gU8 mf_bwfont_render_character(const struct mf_font_s *font, range = find_char_range(bwfont, character, &index); if (!range) return 0; - + return render_char(range, x0, y0, index, callback, state); } @@ -139,7 +139,7 @@ gU8 mf_bwfont_character_width(const struct mf_font_s *font, range = find_char_range(bwfont, character, &index); if (!range) return 0; - + return get_width(range, index); } diff --git a/src/gdisp/mcufont/mf_config.h b/src/gdisp/mcufont/mf_config.h index bf93f992..c241eb4c 100644 --- a/src/gdisp/mcufont/mf_config.h +++ b/src/gdisp/mcufont/mf_config.h @@ -43,8 +43,9 @@ #define MF_USE_KERNING GDISP_NEED_TEXT_KERNING #define MF_FONT_FILE_NAME "src/gdisp/fonts/fonts.h" -/* These are not used for now */ -#define MF_USE_JUSTIFY 0 +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#define pgm_read_word(addr) (*(const uint16_t *)(addr)) + /******************************************************* * Configuration settings related to build environment * @@ -168,7 +169,7 @@ #ifdef __cplusplus #define MF_EXTERN extern "C" #else -#define MF_EXTERN +#define MF_EXTERN extern #endif #endif diff --git a/src/gdisp/mcufont/mf_encoding.c b/src/gdisp/mcufont/mf_encoding.c index ba9fc7c0..d0e0ad5f 100644 --- a/src/gdisp/mcufont/mf_encoding.c +++ b/src/gdisp/mcufont/mf_encoding.c @@ -20,9 +20,9 @@ mf_char mf_getchar(mf_str *str) c = **str; if (!c) return 0; - + (*str)++; - + if ((c & 0x80) == 0) { /* Just normal ASCII character. */ @@ -54,14 +54,14 @@ mf_char mf_getchar(mf_str *str) { seqlen++; tmp >>= 1; - + result = (result << 6) | (**str & 0x3F); (*str)++; } - + result = (result << 6) | (**str & 0x3F); (*str)++; - + result |= (c & (tmp - 1)) << ((seqlen - 1) * 6); return result; } @@ -70,7 +70,7 @@ mf_char mf_getchar(mf_str *str) void mf_rewind(mf_str *str) { (*str)--; - + while ((**str & 0x80) != 0x00 && (**str & 0xC0) != 0xC0) (*str)--; } @@ -87,7 +87,7 @@ mf_char mf_getchar(mf_str *str) void mf_rewind(mf_str *str) { - (*str)--; + (*str)--; } #endif diff --git a/src/gdisp/mcufont/mf_encoding.h b/src/gdisp/mcufont/mf_encoding.h index 7c49f02a..e9a01bd3 100644 --- a/src/gdisp/mcufont/mf_encoding.h +++ b/src/gdisp/mcufont/mf_encoding.h @@ -40,10 +40,10 @@ typedef const wchar_t * mf_str; /* Returns the next character in the string and advances the pointer. * When the string ends, returns 0 and leaves the pointer at the 0 byte. - * + * * str: Pointer to variable holding current location in string. * Initialize it to the start of the string. - * + * * Returns: The next character, as unicode codepoint. */ MF_EXTERN mf_char mf_getchar(mf_str *str); diff --git a/src/gdisp/mcufont/mf_font.c b/src/gdisp/mcufont/mf_font.c index 09182b56..ab15069a 100644 --- a/src/gdisp/mcufont/mf_font.c +++ b/src/gdisp/mcufont/mf_font.c @@ -5,18 +5,9 @@ * http://ugfx.io/license.html */ -#include "mf_config.h" - #ifndef MF_NO_COMPILE -#define MF_BWFONT_INTERNALS -#define MF_RLEFONT_INTERNALS -#define MF_SCALEDFONT_INTERNALS #include "mf_font.h" -#include "mf_rlefont.h" -#include "mf_bwfont.h" -#include "mf_scaledfont.h" - #include /* This will be made into a list of included fonts using macro magic. */ @@ -32,32 +23,77 @@ gU8 mf_render_character(const struct mf_font_s *font, mf_pixel_callback_t callback, void *state) { - gU8 width; - width = font->render_character(font, x0, y0, MFCHAR2UINT16(character), callback, state); - + uint8_t width; + width = font->render_character(font, x0, y0, character, callback, state); + if (!width) { width = font->render_character(font, x0, y0, font->fallback_character, callback, state); } - + return width; } -gU8 mf_character_width(const struct mf_font_s *font, +uint8_t mf_character_width(const struct mf_font_s *font, mf_char character) { - gU8 width; - width = font->character_width(font, MFCHAR2UINT16(character)); - + uint8_t width; + width = font->character_width(font, character); + if (!width) { width = font->character_width(font, font->fallback_character); } - + return width; } +struct whitespace_state +{ + uint8_t min_x, min_y; + uint8_t max_x, max_y; +}; + +static void whitespace_callback(int16_t x, int16_t y, uint8_t count, + uint8_t alpha, void *state) +{ + struct whitespace_state *s = state; + if (alpha > 7) + { + if (s->min_x > x) s->min_x = x; + if (s->min_y > y) s->min_y = y; + x += count - 1; + if (s->max_x < x) s->max_x = x; + if (s->max_y < y) s->max_y = y; + } +} + +MF_EXTERN void mf_character_whitespace(const struct mf_font_s *font, + mf_char character, + uint8_t *left, uint8_t *top, + uint8_t *right, uint8_t *bottom) +{ + struct whitespace_state state = {255, 255, 0, 0}; + mf_render_character(font, 0, 0, character, whitespace_callback, &state); + + if (state.min_x == 255 && state.min_y == 255) + { + /* Character is whitespace */ + if (left) *left = font->width; + if (top) *top = font->height; + if (right) *right = 0; + if (bottom) *bottom = 0; + } + else + { + if (left) *left = state.min_x; + if (top) *top = state.min_y; + if (right) *right = font->width - state.max_x - 1; + if (bottom) *bottom = font->height - state.max_y - 1; + } +} + /* Avoids a dependency on libc */ static bool strequals(const char *a, const char *b) { @@ -73,7 +109,7 @@ const struct mf_font_s *mf_find_font(const char *name) { const struct mf_font_list_s *f; f = MF_INCLUDED_FONTS; - + while (f) { if (strequals(f->font->full_name, name) || @@ -81,14 +117,14 @@ const struct mf_font_s *mf_find_font(const char *name) { return f->font; } - + f = f->next; } - + return 0; } -const struct mf_font_list_s *mf_get_font_list() +const struct mf_font_list_s *mf_get_font_list(void) { return MF_INCLUDED_FONTS; } diff --git a/src/gdisp/mcufont/mf_font.h b/src/gdisp/mcufont/mf_font.h index b69cc782..68481962 100644 --- a/src/gdisp/mcufont/mf_font.h +++ b/src/gdisp/mcufont/mf_font.h @@ -57,13 +57,13 @@ struct mf_font_s /* Function to get character width. Should return 0 if character is * not found. */ - gU8 (*character_width)(const struct mf_font_s *font, gU16 character); + gU8 (*character_width)(const struct mf_font_s *font, mf_char character); /* Function to render a character. Returns the character width or 0 if * character is not found. */ gU8 (*render_character)(const struct mf_font_s *font, gI16 x0, gI16 y0, - gU16 character, + mf_char character, mf_pixel_callback_t callback, void *state); }; @@ -101,13 +101,32 @@ MF_EXTERN gU8 mf_render_character(const struct mf_font_s *font, * data, but rather the tracking width. * * font: Pointer to the font definition. - * character: The character code (unicode) to render. + * character: The character code (unicode) to check width of. * * Returns width of the character in pixels. */ -MF_EXTERN gU8 mf_character_width(const struct mf_font_s *font, +MF_EXTERN uint8_t mf_character_width(const struct mf_font_s *font, mf_char character); +/* Count the amount of white space at the borders of a character. + * + * E.g. if the font->width and font->height are 10x20, but the character + * is only a thin line at the very left edge, this function will return + * (0, 0, 9, 0). If the character is fully whitespace, the function will + * return (10, 20, 0, 0). + * + * font: Pointer to the font definition. + * character: The character code (unicode) to check white space of. + * left: Number of empty rows at left edge. Can be NULL. + * top: Number of empty rows at top edge. Can be NULL. + * right: Number of empty rows at right edge. Can be NULL. + * bottom: Number of empty rows at bottom edge. Can be NULL. + */ +MF_EXTERN void mf_character_whitespace(const struct mf_font_s *font, + mf_char character, + uint8_t *left, uint8_t *top, + uint8_t *right, uint8_t *bottom); + /* Find a font based on name. The name can be either short name or full name. * Note: You can pass MF_INCLUDED_FONTS to search among all the included .h * files. diff --git a/src/gdisp/mcufont/mf_justify.c b/src/gdisp/mcufont/mf_justify.c index 58f87cc3..7965d677 100644 --- a/src/gdisp/mcufont/mf_justify.c +++ b/src/gdisp/mcufont/mf_justify.c @@ -18,14 +18,14 @@ static gI16 mf_round_to_tab(const struct mf_font_s *font, gI16 tabw, dx; tabw = mf_character_width(font, 'm') * MF_TABSIZE; - + /* Always atleast 1 space */ x += mf_character_width(font, ' '); - + /* Round to next tab stop */ dx = x - x0 + font->baseline_x; x += tabw - (dx % tabw); - + return x; } @@ -36,14 +36,14 @@ static gI16 mf_round_to_prev_tab(const struct mf_font_s *font, gI16 tabw, dx; tabw = mf_character_width(font, 'm') * MF_TABSIZE; - + /* Always atleast 1 space */ x -= mf_character_width(font, ' '); - + /* Round to previous tab stop */ dx = x0 - x + font->baseline_x; x -= tabw - (dx % tabw); - + return x; } #endif @@ -56,7 +56,7 @@ gI16 mf_get_string_width(const struct mf_font_s *font, mf_str text, if (!count) count = 0xFFFF; - + while (count-- && *text) { c2 = mf_getchar(&text); @@ -71,14 +71,14 @@ gI16 mf_get_string_width(const struct mf_font_s *font, mf_str text, c2 = ' '; #endif } - + if (kern && c1 != 0) result += mf_compute_kerning(font, c1, c2); result += mf_character_width(font, c2); c1 = c2; } - + return result; } @@ -87,10 +87,10 @@ static gU16 strip_spaces(mf_str text, gU16 count, mf_char *last_char) { gU16 i = 0, result = 0; mf_char tmp = 0; - + if (!count) count = 0xFFFF; - + while (count-- && *text) { i++; @@ -101,7 +101,7 @@ static gU16 strip_spaces(mf_str text, gU16 count, mf_char *last_char) result = i; } } - + if (last_char) { if (!*text) @@ -109,7 +109,7 @@ static gU16 strip_spaces(mf_str text, gU16 count, mf_char *last_char) else *last_char = tmp; } - + return result; } @@ -122,12 +122,12 @@ static void render_left(const struct mf_font_s *font, { gI16 x; mf_char c1 = 0, c2; - + x = x0 - font->baseline_x; while (count--) { c2 = mf_getchar(&text); - + if (c2 == '\t') { #if MF_USE_TABS @@ -138,7 +138,7 @@ static void render_left(const struct mf_font_s *font, c2 = ' '; #endif } - + if (c1 != 0) x += mf_compute_kerning(font, c1, c2); @@ -174,18 +174,18 @@ static void render_right(const struct mf_font_s *font, gU16 i; mf_char c1, c2 = 0; mf_str tmp; - + /* Go to the end of the line. */ for (i = 0; i < count; i++) mf_getchar(&text); - + x = x0 - font->baseline_x; for (i = 0; i < count; i++) { mf_rewind(&text); tmp = text; c1 = mf_getchar(&tmp); - + /* Perform tab alignment */ if (c1 == '\t') { @@ -197,14 +197,14 @@ static void render_right(const struct mf_font_s *font, c1 = ' '; #endif } - + /* Apply the nominal character width */ x -= mf_character_width(font, c1); - + /* Apply kerning */ if (c2 != 0) x -= mf_compute_kerning(font, c1, c2); - + callback(x, y0, c1, state); c2 = c1; } @@ -219,7 +219,7 @@ void mf_render_aligned(const struct mf_font_s *font, { gI16 string_width; count = strip_spaces(text, count, 0); - + if (align == MF_ALIGN_LEFT) { render_left(font, x0, y0, text, count, callback, state); @@ -247,7 +247,6 @@ void mf_render_justified(const struct mf_font_s *font, mf_character_callback_t callback, void *state) { - (void) width; mf_render_aligned(font, x0, y0, MF_ALIGN_LEFT, text, count, callback, state); } @@ -281,20 +280,20 @@ void mf_render_justified(const struct mf_font_s *font, gI16 string_width, adjustment; gU16 num_spaces; mf_char last_char; - + count = strip_spaces(text, count, &last_char); - + if (last_char == '\n' || last_char == 0) { /* Line ends in linefeed, do not justify. */ render_left(font, x0, y0, text, count, callback, state); return; } - + string_width = mf_get_string_width(font, text, count, false); adjustment = width - string_width; num_spaces = count_spaces(text, count); - + { gI16 x, tmp; mf_char c1 = 0, c2; @@ -303,7 +302,7 @@ void mf_render_justified(const struct mf_font_s *font, while (count--) { c2 = mf_getchar(&text); - + if (c2 == '\t') { #if MF_USE_TABS @@ -316,7 +315,7 @@ void mf_render_justified(const struct mf_font_s *font, c2 = ' '; #endif } - + if (is_justify_space(c2)) { tmp = (adjustment + num_spaces / 2) / num_spaces; @@ -324,7 +323,7 @@ void mf_render_justified(const struct mf_font_s *font, num_spaces--; x += tmp; } - + if (c1 != 0) { tmp = mf_compute_kerning(font, c1, c2); diff --git a/src/gdisp/mcufont/mf_kerning.c b/src/gdisp/mcufont/mf_kerning.c index 1e29b6e2..4237d0c9 100644 --- a/src/gdisp/mcufont/mf_kerning.c +++ b/src/gdisp/mcufont/mf_kerning.c @@ -40,7 +40,7 @@ static void fit_rightedge(gI16 x, gI16 y, gU8 count, gU8 alpha, void *state) { struct kerning_state_s *s = state; - + if (alpha > 7) { gU8 zone = y / s->zoneheight; @@ -56,12 +56,12 @@ static bool do_kerning(mf_char c) /* Just a speed optimization, spaces would be ignored anyway. */ if (c == ' ' || c == '\n' || c == '\r' || c == '\t') return false; - + /* Do not kern against digits, in order to keep values in tables nicely * aligned. Most fonts have constant width for digits. */ if (c >= '0' && c <= '9') return false; - + return true; } @@ -78,14 +78,14 @@ gI8 mf_compute_kerning(const struct mf_font_s *font, if (font->flags & MF_FONT_FLAG_MONOSPACE) return 0; /* No kerning for monospace fonts */ - + if (!do_kerning(c1) || !do_kerning(c2)) return 0; - + /* Compute the height of one kerning zone in pixels */ i = (font->height + MF_KERNING_ZONES - 1) / MF_KERNING_ZONES; if (i < 1) i = 1; - + /* Initialize structures */ leftedge.zoneheight = rightedge.zoneheight = i; for (i = 0; i < MF_KERNING_ZONES; i++) @@ -93,11 +93,11 @@ gI8 mf_compute_kerning(const struct mf_font_s *font, leftedge.edgepos[i] = 255; rightedge.edgepos[i] = 0; } - + /* Analyze the edges of both glyphs. */ w1 = mf_render_character(font, 0, 0, c1, fit_rightedge, &rightedge); w2 = mf_render_character(font, 0, 0, c2, fit_leftedge, &leftedge); - + /* Find the minimum horizontal space between the glyphs. */ min_space = 255; for (i = 0; i < MF_KERNING_ZONES; i++) @@ -105,24 +105,24 @@ gI8 mf_compute_kerning(const struct mf_font_s *font, gU8 space; if (leftedge.edgepos[i] == 255 || rightedge.edgepos[i] == 0) continue; /* Outside glyph area. */ - + space = w1 - rightedge.edgepos[i] + leftedge.edgepos[i]; if (space < min_space) min_space = space; } - + if (min_space == 255) return 0; /* One of the characters is space, or both are punctuation. */ - + /* Compute the adjustment of the glyph position. */ normal_space = avg16(w1, w2) * MF_KERNING_SPACE_PERCENT / 100; normal_space += MF_KERNING_SPACE_PIXELS; adjust = normal_space - min_space; max_adjust = -max16(w1, w2) * MF_KERNING_LIMIT / 100; - + if (adjust > 0) adjust = 0; if (adjust < max_adjust) adjust = max_adjust; - + return adjust; } diff --git a/src/gdisp/mcufont/mf_kerning.h b/src/gdisp/mcufont/mf_kerning.h index c6c2dcc7..2ae1cd47 100644 --- a/src/gdisp/mcufont/mf_kerning.h +++ b/src/gdisp/mcufont/mf_kerning.h @@ -17,18 +17,18 @@ #include "mf_rlefont.h" /* Compute the kerning adjustment when c1 is followed by c2. - * + * * font: Pointer to the font definition. * c1: The previous character. * c2: The next character to render. - * + * * Returns the offset to add to the x position for c2. */ #if MF_USE_KERNING MF_EXTERN gI8 mf_compute_kerning(const struct mf_font_s *font, mf_char c1, mf_char c2); #else -#define mf_compute_kerning(font, c1, c2) 0 +#define mf_compute_kerning(f,c1,c2) (0) #endif #endif diff --git a/src/gdisp/mcufont/mf_rlefont.c b/src/gdisp/mcufont/mf_rlefont.c index 1da265c3..b96ab3ad 100644 --- a/src/gdisp/mcufont/mf_rlefont.c +++ b/src/gdisp/mcufont/mf_rlefont.c @@ -46,7 +46,7 @@ static const gU8 *find_glyph(const struct mf_rlefont_s *font, index = character - range->first_char; if (character >= range->first_char && index < range->char_count) { - unsigned offset = range->glyph_offsets[index]; + uint16_t offset = pgm_read_word(range->glyph_offsets + index); return &range->glyph_data[offset]; } } @@ -75,7 +75,7 @@ static void write_pixels(struct renderstate_r *rstate, gU16 count, gU8 rowlen; /* Write row-by-row if the run spans multiple rows. */ - while (rstate->x + count >= rstate->x_end) + while ((int32_t)rstate->x + count >= rstate->x_end) { rowlen = rstate->x_end - rstate->x; rstate->callback(rstate->x, rstate->y, rowlen, alpha, rstate->state); @@ -83,7 +83,7 @@ static void write_pixels(struct renderstate_r *rstate, gU16 count, rstate->x = rstate->x_begin; rstate->y++; } - + /* Write the remaining part */ if (count) { @@ -108,13 +108,13 @@ static void write_rle_dictentry(const struct mf_rlefont_s *font, struct renderstate_r *rstate, gU8 index) { - gU16 offset = font->dictionary_offsets[index]; - gU16 length = font->dictionary_offsets[index + 1] - offset; - gU16 i; - + uint16_t offset = pgm_read_word(font->dictionary_offsets + index); + uint16_t length = pgm_read_word(font->dictionary_offsets + index + 1) - offset; + uint16_t i; + for (i = 0; i < length; i++) { - gU8 code = font->dictionary_data[offset + i]; + uint8_t code = pgm_read_byte(font->dictionary_data + offset + i); if ((code & RLE_CODEMASK) == RLE_ZEROS) { skip_pixels(rstate, code & RLE_VALMASK); @@ -159,31 +159,31 @@ static void write_bin_codeword(const struct mf_rlefont_s *font, struct renderstate_r *rstate, gU8 code) { - gU8 bitcount = fillentry_bitcount(code); - gU8 byte = code - DICT_START7BIT; - gU8 runlen = 0; - (void) font; - + (void)font; + uint8_t bitcount = fillentry_bitcount(code); + uint8_t byte = code - DICT_START7BIT; + uint8_t runlen = 0; + while (bitcount--) { if (byte & 1) { runlen++; } - else + else { if (runlen) { write_pixels(rstate, runlen, 255); runlen = 0; } - + skip_pixels(rstate, 1); } - + byte >>= 1; } - + if (runlen) write_pixels(rstate, runlen, 255); } @@ -191,9 +191,13 @@ static void write_bin_codeword(const struct mf_rlefont_s *font, /* Decode and write out a reference codeword */ static void write_ref_codeword(const struct mf_rlefont_s *font, struct renderstate_r *rstate, - gU8 code) + uint8_t code) { - if (code <= 15) + if (code == 0) + { + skip_pixels(rstate, 1); + } + else if (code <= 15) { write_pixels(rstate, 1, 0x11 * code); } @@ -219,15 +223,15 @@ static void write_ref_codeword(const struct mf_rlefont_s *font, /* Decode and write out a reference encoded dictionary entry. */ static void write_ref_dictentry(const struct mf_rlefont_s *font, struct renderstate_r *rstate, - gU8 index) + uint8_t index) { - gU16 offset = font->dictionary_offsets[index]; - gU16 length = font->dictionary_offsets[index + 1] - offset; - gU16 i; - + uint16_t offset = pgm_read_word(font->dictionary_offsets + index); + uint16_t length = pgm_read_word(font->dictionary_offsets + index + 1) - offset; + uint16_t i; + for (i = 0; i < length; i++) { - gU8 code = font->dictionary_data[offset + i]; + uint8_t code = pgm_read_byte(font->dictionary_data + offset + i); write_ref_codeword(font, rstate, code); } } @@ -235,7 +239,7 @@ static void write_ref_dictentry(const struct mf_rlefont_s *font, /* Decode and write out an arbitrary glyph codeword */ static void write_glyph_codeword(const struct mf_rlefont_s *font, struct renderstate_r *rstate, - gU8 code) + uint8_t code) { if (code >= DICT_START + font->rle_entry_count && code < DICT_START + font->dict_entry_count) @@ -249,15 +253,15 @@ static void write_glyph_codeword(const struct mf_rlefont_s *font, } -gU8 mf_rlefont_render_character(const struct mf_font_s *font, - gI16 x0, gI16 y0, - gU16 character, +uint8_t mf_rlefont_render_character(const struct mf_font_s *font, + int16_t x0, int16_t y0, + uint16_t character, mf_pixel_callback_t callback, void *state) { - const gU8 *p; - gU8 width; - + const uint8_t *p; + uint8_t width; + struct renderstate_r rstate; rstate.x_begin = x0; rstate.x_end = x0 + font->width; @@ -266,29 +270,28 @@ gU8 mf_rlefont_render_character(const struct mf_font_s *font, rstate.y_end = y0 + font->height; rstate.callback = callback; rstate.state = state; - - p = find_glyph((struct mf_rlefont_s*)font, character); - if (!p) - return 0; - - width = *p++; - while (rstate.y < rstate.y_end) - { - write_glyph_codeword((struct mf_rlefont_s*)font, &rstate, *p++); - } - - return width; -} -gU8 mf_rlefont_character_width(const struct mf_font_s *font, - gU16 character) -{ - const gU8 *p; p = find_glyph((struct mf_rlefont_s*)font, character); if (!p) return 0; - - return *p; + + width = pgm_read_byte(p++); + while (rstate.y < rstate.y_end) + { + write_glyph_codeword((struct mf_rlefont_s*)font, &rstate, pgm_read_byte(p++)); + } + + return width; } +uint8_t mf_rlefont_character_width(const struct mf_font_s *font, + uint16_t character) +{ + const uint8_t *p; + p = find_glyph((struct mf_rlefont_s*)font, character); + if (!p) + return 0; + #endif //MF_NO_COMPILE + return pgm_read_byte(p); +} diff --git a/src/gdisp/mcufont/mf_rlefont.h b/src/gdisp/mcufont/mf_rlefont.h index be21fe88..60ee6ae1 100644 --- a/src/gdisp/mcufont/mf_rlefont.h +++ b/src/gdisp/mcufont/mf_rlefont.h @@ -39,7 +39,7 @@ struct mf_rlefont_char_range_s struct mf_rlefont_s { struct mf_font_s font; - + /* Version of the font definition used. */ const gU8 version; diff --git a/src/gdisp/mcufont/mf_scaledfont.c b/src/gdisp/mcufont/mf_scaledfont.c index 9e0903cc..995abba5 100644 --- a/src/gdisp/mcufont/mf_scaledfont.c +++ b/src/gdisp/mcufont/mf_scaledfont.c @@ -28,27 +28,27 @@ static void scaled_pixel_callback(gI16 x, gI16 y, gU8 count, count *= rstate->x_scale; x = rstate->x0 + x * rstate->x_scale; y = rstate->y0 + y * rstate->y_scale; - + for (dy = 0; dy < rstate->y_scale; dy++) { rstate->orig_callback(x, y + dy, count, alpha, rstate->orig_state); } } - -gU8 mf_scaled_character_width(const struct mf_font_s *font, - gU16 character) + +static gU8 scaled_character_width(const struct mf_font_s *font, + mf_char character) { struct mf_scaledfont_s *sfont = (struct mf_scaledfont_s*)font; gU8 basewidth; basewidth = sfont->basefont->character_width(sfont->basefont, character); - + return sfont->x_scale * basewidth; } -gU8 mf_scaled_render_character(const struct mf_font_s *font, - gI16 x0, gI16 y0, - gU16 character, +static gU8 scaled_render_character(const struct mf_font_s *font, + int16_t x0, int16_t y0, + mf_char character, mf_pixel_callback_t callback, void *state) { @@ -62,10 +62,10 @@ gU8 mf_scaled_render_character(const struct mf_font_s *font, rstate.y_scale = sfont->y_scale; rstate.x0 = x0; rstate.y0 = y0; - + basewidth = sfont->basefont->render_character(sfont->basefont, 0, 0, character, scaled_pixel_callback, &rstate); - + return sfont->x_scale * basewidth; } @@ -75,7 +75,7 @@ void mf_scale_font(struct mf_scaledfont_s *newfont, { newfont->font = *basefont; newfont->basefont = basefont; - + newfont->font.width *= x_scale; newfont->font.height *= y_scale; newfont->font.baseline_x *= x_scale; @@ -83,9 +83,9 @@ void mf_scale_font(struct mf_scaledfont_s *newfont, newfont->font.min_x_advance *= x_scale; newfont->font.max_x_advance *= x_scale; newfont->font.line_height *= y_scale; - newfont->font.character_width = &mf_scaled_character_width; - newfont->font.render_character = &mf_scaled_render_character; - + newfont->font.character_width = &scaled_character_width; + newfont->font.render_character = &scaled_render_character; + newfont->x_scale = x_scale; newfont->y_scale = y_scale; } diff --git a/src/gdisp/mcufont/mf_scaledfont.h b/src/gdisp/mcufont/mf_scaledfont.h index da9f47aa..f84d3d5d 100644 --- a/src/gdisp/mcufont/mf_scaledfont.h +++ b/src/gdisp/mcufont/mf_scaledfont.h @@ -17,26 +17,14 @@ struct mf_scaledfont_s { struct mf_font_s font; - + const struct mf_font_s *basefont; - gU8 x_scale; - gU8 y_scale; + uint8_t x_scale; + uint8_t y_scale; }; MF_EXTERN void mf_scale_font(struct mf_scaledfont_s *newfont, const struct mf_font_s *basefont, gU8 x_scale, gU8 y_scale); -#ifdef MF_SCALEDFONT_INTERNALS -/* Internal functions, don't use these directly. */ -MF_EXTERN gU8 mf_scaled_render_character(const struct mf_font_s *font, - gI16 x0, gI16 y0, - gU16 character, - mf_pixel_callback_t callback, - void *state); - -MF_EXTERN gU8 mf_scaled_character_width(const struct mf_font_s *font, - gU16 character); -#endif - #endif diff --git a/src/gdisp/mcufont/mf_wordwrap.c b/src/gdisp/mcufont/mf_wordwrap.c index 0b303ace..32e215b8 100644 --- a/src/gdisp/mcufont/mf_wordwrap.c +++ b/src/gdisp/mcufont/mf_wordwrap.c @@ -43,7 +43,7 @@ static bool get_wordlen(const struct mf_font_s *font, mf_str *text, result->chars++; result->word += mf_character_width(font, c); - prev = *text; + prev = *text; c = mf_getchar(text); } @@ -56,10 +56,10 @@ static bool get_wordlen(const struct mf_font_s *font, mf_str *text, else if (c == '\t') result->space += mf_character_width(font, 'm') * MF_TABSIZE; else if (c == '\n') { - /* Special case for newlines, skip the character then break. */ - prev = *text; + /* Special case for newlines, skip the character then break. */ + prev = *text; break; - } + } prev = *text; c = mf_getchar(text); @@ -239,6 +239,7 @@ void mf_wordwrap(const struct mf_font_s *font, gI16 width, void mf_wordwrap(const struct mf_font_s *font, gI16 width, mf_str text, mf_line_callback_t callback, void *state) { + mf_str orig = text; mf_str linestart; /* Current line width and character count */ diff --git a/src/gdisp/mcufont/mf_wordwrap.h b/src/gdisp/mcufont/mf_wordwrap.h index 91ac8cad..57967398 100644 --- a/src/gdisp/mcufont/mf_wordwrap.h +++ b/src/gdisp/mcufont/mf_wordwrap.h @@ -20,14 +20,14 @@ * line: Pointer to the beginning of the string for this line. * count: Number of characters on the line. * state: Free variable that was passed to wordwrap(). - * + * * Returns: true to continue, false to stop after this line. */ typedef bool (*mf_line_callback_t) (mf_str line, gU16 count, void *state); /* Word wrap a piece of text. Calls the callback function for each line. - * + * * font: Font to use for metrics. * width: Maximum line width in pixels. * text: Pointer to the start of the text to process. @@ -35,5 +35,5 @@ typedef bool (*mf_line_callback_t) (mf_str line, gU16 count, */ MF_EXTERN void mf_wordwrap(const struct mf_font_s *font, gI16 width, mf_str text, mf_line_callback_t callback, void *state); - + #endif