render-cg: 8x9 font and proportional font rendering

This commit is contained in:
lephe 2019-06-23 17:27:44 -04:00
parent 0055199359
commit 11b40b445c
6 changed files with 100 additions and 43 deletions

View File

@ -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,
};

View File

@ -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.

BIN
src/font8x9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -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);
}

View File

@ -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],

View File

@ -2,6 +2,10 @@
#include <gint/display.h>
#include <display/common.h>
/* 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;
}