From 11b40b445c4ea51f5770b33f223a6de09653cbf9 Mon Sep 17 00:00:00 2001 From: lephe Date: Sun, 23 Jun 2019 17:27:44 -0400 Subject: [PATCH] render-cg: 8x9 font and proportional font rendering --- include/gint/display-cg.h | 6 +++++ make/Makefile | 7 +++++- src/font8x9.png | Bin 0 -> 17353 bytes src/render-cg/topti.c | 47 ++++++++++++++++++++++++++++++-------- src/render-fx/topti.c | 44 +++++++++-------------------------- src/render/topti.c | 39 +++++++++++++++++++++++++++++++ 6 files changed, 100 insertions(+), 43 deletions(-) create mode 100644 src/font8x9.png diff --git a/include/gint/display-cg.h b/include/gint/display-cg.h index de0919e..2c513bb 100644 --- a/include/gint/display-cg.h +++ b/include/gint/display-cg.h @@ -32,6 +32,12 @@ extern uint16_t *vram; typedef uint16_t color_t; enum { + /* Compatibility with fx9860g color names */ + color_white = 0xffff, + color_light = 0xaaaa, + color_dark = 0x5555, + color_black = 0x0000, + color_none = -1, }; diff --git a/make/Makefile b/make/Makefile index 0e1affb..cc3818b 100755 --- a/make/Makefile +++ b/make/Makefile @@ -54,7 +54,7 @@ src_obj := $(foreach s,$(src),$(call src2obj,$s)) # Files with special handling spe-fx := ../src/font5x7.png -spe-cg := ../src/font10x12.png +spe-cg := ../src/font10x12.png ../src/font8x9.png spe_obj := version.o $(foreach s,$(spe-$(CONFIG.TARGET)),$(call src2obj,$s)) # All object files @@ -112,6 +112,11 @@ $(call src2obj,../src/font10x12.png): ../src/font10x12.png @ mkdir -p $(dir $@) $(call cmd_m,fxconv,font10x12.png)$(conv) -f $< -o $@ name:gint_font10x12 \ charset:print grid.size:10x12 grid.padding:0 grid.border:3 +$(call src2obj,../src/font8x9.png): ../src/font8x9.png + @ mkdir -p $(dir $@) + $(call cmd_m,fxconv,font8x9.png)$(conv) -f $< -o $@ name:gint_font8x9 \ + charset:print grid.size:8x11 grid.padding:1 grid.border:0 \ + proportional:true # Version symbol. ld generates a .stack section for unknown reasons; I remove # it in the linker script. diff --git a/src/font8x9.png b/src/font8x9.png new file mode 100644 index 0000000000000000000000000000000000000000..8f9b8ed96b33f0cd889229e7532a214a5459eba0 GIT binary patch literal 17353 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 AUH||9 literal 0 HcmV?d00001 diff --git a/src/render-cg/topti.c b/src/render-cg/topti.c index 538b16c..5b4bda0 100644 --- a/src/render-cg/topti.c +++ b/src/render-cg/topti.c @@ -43,13 +43,19 @@ void topti_glyph(uint16_t *vram, uint32_t const * data, int left, int top, } GSECTION(".pretext") -void topti_render(int x, int y, const char *str, size_t size, font_t const *f, +void topti_render(int x, int y, char const *str, size_t size, font_t const *f, int fg, int bg) { /* Raw glyph data */ - uint32_t const * data = f->prop - ? (void *)(f->sized_data + charset_size(f->charset)) - : f->data; + uint32_t const * data; + if(!f->prop) data = f->data; + else + { + int cs = charset_size(f->charset); + /* 4-align the result */ + cs += (4 - cs) & 3; + data = (void *)(f->sized_data + cs); + } /* Storage height, top position within glyph */ int height = f->data_height, top = 0; @@ -62,15 +68,29 @@ void topti_render(int x, int y, const char *str, size_t size, font_t const *f, /* Move to top row */ uint16_t *target = vram + 396 * y; - /* Character spacing */ - int space = 2; + /* Character spacing and space waiting to be drawn */ + int space = 1; + int active_space = 0; /* Read each character from the input string */ while(size--) { - int glyph = charset_decode(f->charset, *str++); + int c = *str++; + + int glyph = charset_decode(f->charset, c); if(glyph < 0) continue; + /* Draw the space if background is opaque */ + int prop_space = (c == ' ' && f->prop) ? 5 : 0; + if((active_space && bg >= 0) || prop_space) + { + active_space += prop_space; + drect(x, y, x + active_space - 1, y + height - 1, bg); + } + x += active_space; + if(prop_space) { active_space = space; continue; } + if(x >= 396) break; + int index = topti_offset(f, glyph); /* Compute horizontal intersection between glyph and screen */ @@ -80,7 +100,8 @@ void topti_render(int x, int y, const char *str, size_t size, font_t const *f, if(x + dataw <= 0) { - x += dataw + space; + x += dataw; + active_space = space; continue; } if(x < 0) left = -x, width += x; @@ -91,6 +112,14 @@ void topti_render(int x, int y, const char *str, size_t size, font_t const *f, topti_glyph(target + x, data + index, left, top, width, height, dataw, fg, bg); - x += dataw + space; + x += dataw; + active_space = space; } } + +/* dtext() - display a string of text */ +GSECTION(".pretext") +void dtext(int x, int y, char const *str, int fg, int bg) +{ + topti_render(x, y, str, strlen(str), topti_font, fg, bg); +} diff --git a/src/render-fx/topti.c b/src/render-fx/topti.c index cea4803..4ad5ef8 100644 --- a/src/render-fx/topti.c +++ b/src/render-fx/topti.c @@ -91,15 +91,21 @@ int topti_split(uint32_t const * glyph, int width, int height, int free, @asm_fg Assembler function for text rendering @asm_bg Assembler function for background rendering */ GSECTION(".pretext") -void topti_render(int x, int y, const char *str, font_t const *f, +void topti_render(int x, int y, char const *str, font_t const *f, asm_text_t *asm_fg, asm_text_t *asm_bg) { /* Storage height and number of free bits in operators[] */ int height = f->data_height, free; /* Raw glyph data */ - uint32_t const * data = f->prop - ? (void *)(f->sized_data + charset_size(f->charset)) - : f->data; + uint32_t const * data; + if(!f->prop) data = f->data; + else + { + int cs = charset_size(f->charset); + /* 4-align the result */ + cs += (4 - cs) & 3; + data = (void *)(f->sized_data + cs); + } /* Basic clipping */ if(x > 127 || y > 63 || y + height <= 0) return; @@ -179,37 +185,9 @@ void topti_render(int x, int y, const char *str, font_t const *f, } } -/* dsize() - get the width and height of rendered text */ -void dsize(const char *str, font_t const * f, int *w, int *h) -{ - if(!f) f = topti_font; - if(h) *h = f->line_height; - if(!w) return; - - /* Width for monospaced fonts is easy, unfortunately we still need to - compute the length of [str]. Critical applications might do the - product themselves to avoid this cost. */ - if(!f->prop) - { - int length = 0; - while(*str++) length++; - *w = (f->width + 1) * length - 1; - return; - } - - /* For proportional fonts, fetch the width of each individual glyphs */ - int width = 0; - while(*str) - { - int glyph = charset_decode(f->charset, *str++); - if(glyph > 0) width += f->sized_data[glyph] + 1; - } - *w = width - 1; -} - /* dtext() - display a string of text */ GSECTION(".pretext") -void dtext(int x, int y, const char *str, int fg, int bg) +void dtext(int x, int y, char const *str, int fg, int bg) { if((uint)fg >= 8 || (uint)bg >= 8) return; topti_render(x, y, str, topti_font, topti_asm_text[fg], diff --git a/src/render/topti.c b/src/render/topti.c index 037097c..8db4d93 100644 --- a/src/render/topti.c +++ b/src/render/topti.c @@ -2,6 +2,10 @@ #include #include +/* These parameters will eventually be specified by the font */ +#define CHAR_SPACING 1 +#define PROP_SPACING 5 + /* dfont(): Set the default font for text rendering */ GSECTION(".pretext") void dfont(font_t const * font) @@ -71,3 +75,38 @@ int topti_offset(font_t const *f, uint glyph) return offset; } + +/* dsize() - get the width and height of rendered text */ +void dsize(const char *str, font_t const * f, int *w, int *h) +{ + if(!f) f = topti_font; + if(h) *h = f->line_height; + if(!w) return; + + /* Width for monospaced fonts is easy, unfortunately we still need to + compute the length of [str]. Critical applications might do the + product themselves to avoid this cost. */ + if(!f->prop) + { + int length = 0; + while(*str++) length++; + *w = (f->width + CHAR_SPACING) * length - CHAR_SPACING; + return; + } + + /* For proportional fonts, fetch the width of each individual glyphs */ + int width = 0, c; + + while((c = *str++)) + { + if(c == ' ') + { + width += PROP_SPACING + CHAR_SPACING; + continue; + } + + int glyph = charset_decode(f->charset, c); + if(glyph > 0) width += f->sized_data[glyph] + CHAR_SPACING; + } + *w = width - CHAR_SPACING; +}