gdisp: Update font decoder
This commit is contained in:
parent
bfc28ae986
commit
44ef4ac25b
@ -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
|
||||
|
@ -87,7 +87,7 @@ mf_char mf_getchar(mf_str *str)
|
||||
|
||||
void mf_rewind(mf_str *str)
|
||||
{
|
||||
(*str)--;
|
||||
(*str)--;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -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 <stdbool.h>
|
||||
|
||||
/* This will be made into a list of included fonts using macro magic. */
|
||||
@ -32,8 +23,8 @@ 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)
|
||||
{
|
||||
@ -44,11 +35,11 @@ gU8 mf_render_character(const struct mf_font_s *font,
|
||||
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)
|
||||
{
|
||||
@ -58,6 +49,51 @@ gU8 mf_character_width(const struct mf_font_s *font,
|
||||
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)
|
||||
{
|
||||
@ -88,7 +124,7 @@ const struct mf_font_s *mf_find_font(const char *name)
|
||||
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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
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
|
||||
|
@ -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);
|
||||
@ -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,10 +159,10 @@ 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--)
|
||||
{
|
||||
@ -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,14 +253,14 @@ 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;
|
||||
@ -267,28 +271,27 @@ gU8 mf_rlefont_render_character(const struct mf_font_s *font,
|
||||
rstate.callback = callback;
|
||||
rstate.state = state;
|
||||
|
||||
p = find_glyph((struct mf_rlefont_s*)font, character);
|
||||
p = find_glyph((struct mf_rlefont_s*)font, character);
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
width = *p++;
|
||||
width = pgm_read_byte(p++);
|
||||
while (rstate.y < rstate.y_end)
|
||||
{
|
||||
write_glyph_codeword((struct mf_rlefont_s*)font, &rstate, *p++);
|
||||
write_glyph_codeword((struct mf_rlefont_s*)font, &rstate, pgm_read_byte(p++));
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
gU8 mf_rlefont_character_width(const struct mf_font_s *font,
|
||||
gU16 character)
|
||||
uint8_t mf_rlefont_character_width(const struct mf_font_s *font,
|
||||
uint16_t character)
|
||||
{
|
||||
const gU8 *p;
|
||||
const uint8_t *p;
|
||||
p = find_glyph((struct mf_rlefont_s*)font, character);
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
#endif //MF_NO_COMPILE
|
||||
return pgm_read_byte(p);
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ static void scaled_pixel_callback(gI16 x, gI16 y, gU8 count,
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@ -46,9 +46,9 @@ gU8 mf_scaled_character_width(const struct mf_font_s *font,
|
||||
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)
|
||||
{
|
||||
@ -83,8 +83,8 @@ 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;
|
||||
|
@ -19,24 +19,12 @@ 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
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user