From 240f29f9d55e1e26053c241e378ec411128b028e Mon Sep 17 00:00:00 2001 From: Lephe Date: Mon, 5 Oct 2020 16:11:14 +0200 Subject: [PATCH] topti: custom character and word spacing (#13) This commit introduces custom character spacing with a new fxconv parameter "char-spacing". Word spacing is also tied to the width of the space character (0x20). This removes the need for special semantics on the space character, but requires that its size be specified with gray pixels for proportional fonts. This also fixes problems with the size of spaces in dsize() not being correlated with their size during rendering, since on fx-9860G topti already used the glyph's with as word spacing. Since fxconv changes but gint's Makefile does not track updates to external tools, a full rebuild of gint is required past this commit. --- include/gint/display.h | 5 +++++ src/font8x9.png | Bin 17300 -> 17324 bytes src/render-cg/topti.c | 25 +++++++++---------------- src/render-fx/topti.c | 2 +- src/render/topti.c | 21 ++++++++------------- 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/include/gint/display.h b/include/gint/display.h index b43830c..e99eb1e 100644 --- a/include/gint/display.h +++ b/include/gint/display.h @@ -189,6 +189,11 @@ typedef struct /* Number of total glyphs */ uint32_t glyph_count; + /* Character spacing (usually 1) */ + uint8_t char_spacing; + + uint :24; + struct { /* Unicode point of first character in block */ uint start :20; diff --git a/src/font8x9.png b/src/font8x9.png index 5bb9748adc453b18e937c3823d8973d7e79f1130..af01487a08ba5c9bd509ad10978f4eb0cf3bbd09 100644 GIT binary patch literal 17324 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 XkNuY`V7ltb00000NkvXXu0mjfQ6hLx literal 17300 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 ? 5 : 0; - if(active_space || prop_space) - { - active_space += prop_space; - if(bg >= 0) drect(x, y, x + active_space - 1, - y + height - 1, bg); - } - x += active_space; - if(prop_space) { active_space = space; continue; } + int dataw = f->prop ? f->glyph_width[glyph] : f->width; + + /* Draw character spacing if background is opaque */ + if(space && bg >= 0) drect(x, y, x+space-1, y+height-1, bg); + x += space; if(x >= 396) break; int index = topti_offset(f, glyph); /* Compute horizontal intersection between glyph and screen */ - int dataw = f->prop ? f->glyph_width[glyph] : f->width; int width = dataw, left = 0; if(x + dataw <= 0) { x += dataw; - active_space = space; + space = f->char_spacing; continue; } if(x < 0) left = -x, width += x; @@ -108,7 +101,7 @@ static void topti_render(int x, int y, char const *str_char, font_t const *f, dataw, fg, bg); x += dataw; - active_space = space; + space = f->char_spacing; } } diff --git a/src/render-fx/topti.c b/src/render-fx/topti.c index 3f1ad4e..f9db890 100644 --- a/src/render-fx/topti.c +++ b/src/render-fx/topti.c @@ -133,7 +133,7 @@ void topti_render(int x, int y, char const *str_char, font_t const *f, free = topti_split(data+index, width, height, free, operators); /* Potential space after the glyph */ - int space = (*str != 0); + int space = (*str != 0) ? f->char_spacing : 0; free -= space; if(free > 0) continue; diff --git a/src/render/topti.c b/src/render/topti.c index 406ea03..4ce6ae1 100644 --- a/src/render/topti.c +++ b/src/render/topti.c @@ -105,39 +105,34 @@ uint32_t topti_utf8_next(uint8_t const **str_pointer) void dsize(char const *str_char, font_t const * f, int *w, int *h) { uint8_t const *str = (void *)str_char; + uint32_t code_point; 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. */ + compute the length and group bytes into Unicode code points. */ if(!f->prop) { int length = 0; - while(*str++) length++; - *w = (f->width + CHAR_SPACING) * length - CHAR_SPACING; + while((code_point = topti_utf8_next(&str))) length++; + + *w = (f->width + f->char_spacing) * length - f->char_spacing; return; } /* For proportional fonts, fetch the width of each individual glyphs */ int width = 0; - uint32_t code_point; while(1) { code_point = topti_utf8_next(&str); if(!code_point) break; - if(code_point == ' ') - { - width += PROP_SPACING + CHAR_SPACING; - continue; - } - int glyph = topti_glyph_index(f, code_point); - if(glyph >= 0) width += f->glyph_width[glyph] + CHAR_SPACING; + if(glyph < 0) continue; + width += f->glyph_width[glyph] + f->char_spacing; } - *w = width - CHAR_SPACING; + *w = width - f->char_spacing; }