mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-07-11 22:57:34 +02:00
topti: support Unicode in the data structures (WIP)
This change modifies the font_t type to replace the concept of charset with a more generic list of non-overlapping Unicode blocks defined by a starting code point and a size. It also takes advantage of the assembly feature of fxconv, introduced for libimg long after the first version of topti, to support pointers in the converted structure rather than having to tediously compute offsets within a variable-size structure.
This commit is contained in:
parent
77de9e7796
commit
e3042755d2
5 changed files with 58 additions and 106 deletions
|
@ -167,25 +167,38 @@ void dvline(int x, int color);
|
||||||
/* font_t: Font data encoded for topti */
|
/* font_t: Font data encoded for topti */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/* Length of font name (not necessarily NUL-terminated!) */
|
/* Font name (NUL-terminated), NULL if no title */
|
||||||
uint title :5;
|
char const *name;
|
||||||
|
|
||||||
/* Font shape flags */
|
/* Font shape flags */
|
||||||
uint bold :1;
|
uint bold :1;
|
||||||
uint italic :1;
|
uint italic :1;
|
||||||
uint serif :1;
|
uint serif :1;
|
||||||
uint mono :1;
|
uint mono :1;
|
||||||
|
uint :3;
|
||||||
/* Whether data is variable-length (proportional font) */
|
/* Whether data is variable-length (proportional font) */
|
||||||
uint prop :1;
|
uint prop :1;
|
||||||
/* Reserved for future use */
|
|
||||||
uint :2;
|
|
||||||
/* Implemented charcter set */
|
|
||||||
uint charset :4;
|
|
||||||
/* Line height */
|
/* Line height */
|
||||||
uint8_t line_height;
|
uint8_t line_height;
|
||||||
/* Storage height */
|
/* Storage height */
|
||||||
uint8_t data_height;
|
uint8_t data_height;
|
||||||
|
|
||||||
/* The rest of the data depends on whether the font is proportional */
|
/* Number of Unicode blocks */
|
||||||
|
uint8_t block_count;
|
||||||
|
/* Number of total glyphs */
|
||||||
|
uint32_t glyph_count;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/* Unicode point of first character in block */
|
||||||
|
uint start :20;
|
||||||
|
/* Length of block */
|
||||||
|
uint length :12;
|
||||||
|
} *blocks;
|
||||||
|
|
||||||
|
/* Raw glyph data */
|
||||||
|
uint32_t *data;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
/* For monospaced fonts */
|
/* For monospaced fonts */
|
||||||
struct {
|
struct {
|
||||||
|
@ -193,23 +206,16 @@ typedef struct
|
||||||
uint16_t width;
|
uint16_t width;
|
||||||
/* Storage size, in longwords, of each glyph */
|
/* Storage size, in longwords, of each glyph */
|
||||||
uint16_t storage_size;
|
uint16_t storage_size;
|
||||||
/* Raw glyph data */
|
|
||||||
uint32_t data[];
|
|
||||||
};
|
};
|
||||||
/* For proportional fonts */
|
/* For proportional fonts */
|
||||||
struct {
|
struct {
|
||||||
/* Storage index to find glyphs quickly */
|
/* Storage index to find glyphs quickly */
|
||||||
uint16_t index[16];
|
uint16_t *glyph_index;
|
||||||
/* Size array (padded to 4 bytes), 1 byte per entry,
|
/* Width of each individual glyph */
|
||||||
followed by glyph data */
|
uint8_t *glyph_width;
|
||||||
uint8_t sized_data[];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The font name is stored after the data. The size is the length set
|
|
||||||
in the [title] field, padded to 4 bytes with NULs. There might not
|
|
||||||
be a NUL at the end. */
|
|
||||||
|
|
||||||
} GPACKED(4) font_t;
|
} GPACKED(4) font_t;
|
||||||
|
|
||||||
/* dfont(): Set the default font for text rendering
|
/* dfont(): Set the default font for text rendering
|
||||||
|
|
|
@ -46,15 +46,7 @@ void topti_render(int x, int y, char const *str, size_t size, font_t const *f,
|
||||||
int fg, int bg)
|
int fg, int bg)
|
||||||
{
|
{
|
||||||
/* Raw glyph data */
|
/* Raw glyph data */
|
||||||
uint32_t const * data;
|
uint32_t const *data = f->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 */
|
/* Storage height, top position within glyph */
|
||||||
int height = f->data_height, top = 0;
|
int height = f->data_height, top = 0;
|
||||||
|
@ -76,7 +68,7 @@ void topti_render(int x, int y, char const *str, size_t size, font_t const *f,
|
||||||
{
|
{
|
||||||
int c = *str++;
|
int c = *str++;
|
||||||
|
|
||||||
int glyph = charset_decode(f->charset, c);
|
int glyph = topti_glyph_index(f, c);
|
||||||
if(glyph < 0) continue;
|
if(glyph < 0) continue;
|
||||||
|
|
||||||
/* Draw the space if background is opaque */
|
/* Draw the space if background is opaque */
|
||||||
|
@ -95,7 +87,7 @@ void topti_render(int x, int y, char const *str, size_t size, font_t const *f,
|
||||||
|
|
||||||
/* Compute horizontal intersection between glyph and screen */
|
/* Compute horizontal intersection between glyph and screen */
|
||||||
|
|
||||||
int dataw = f->prop ? f->sized_data[glyph] : f->width;
|
int dataw = f->prop ? f->glyph_width[glyph] : f->width;
|
||||||
int width = dataw, left = 0;
|
int width = dataw, left = 0;
|
||||||
|
|
||||||
if(x + dataw <= 0)
|
if(x + dataw <= 0)
|
||||||
|
|
|
@ -88,15 +88,7 @@ void topti_render(int x, int y, char const *str, font_t const *f,
|
||||||
/* Storage height and number of free bits in operators[] */
|
/* Storage height and number of free bits in operators[] */
|
||||||
int height = f->data_height, free;
|
int height = f->data_height, free;
|
||||||
/* Raw glyph data */
|
/* Raw glyph data */
|
||||||
uint32_t const * data;
|
uint32_t const *data = f->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 */
|
/* Basic clipping */
|
||||||
if(x > 127 || y > 63 || y + height <= 0) return;
|
if(x > 127 || y > 63 || y + height <= 0) return;
|
||||||
|
@ -126,13 +118,13 @@ void topti_render(int x, int y, char const *str, font_t const *f,
|
||||||
/* Pull each character into the operator buffer */
|
/* Pull each character into the operator buffer */
|
||||||
while(*str)
|
while(*str)
|
||||||
{
|
{
|
||||||
int glyph = charset_decode(f->charset, *str++);
|
int glyph = topti_glyph_index(f, *str++);
|
||||||
if(glyph < 0) continue;
|
if(glyph < 0) continue;
|
||||||
|
|
||||||
int index = topti_offset(f, glyph);
|
int index = topti_offset(f, glyph);
|
||||||
|
|
||||||
/* Put glyph data into the operators */
|
/* Put glyph data into the operators */
|
||||||
int width = f->prop ? f->sized_data[glyph] : f->width;
|
int width = f->prop ? f->glyph_width[glyph] : f->width;
|
||||||
free = topti_split(data+index, width, height, free, operators);
|
free = topti_split(data+index, width, height, free, operators);
|
||||||
|
|
||||||
/* Potential space after the glyph */
|
/* Potential space after the glyph */
|
||||||
|
|
|
@ -26,29 +26,12 @@ extern font_t const *topti_font;
|
||||||
/* Default font */
|
/* Default font */
|
||||||
extern font_t const *gint_default_font;
|
extern font_t const *gint_default_font;
|
||||||
|
|
||||||
/* enum topti_charset: Available character set decoders
|
/* topti_glyph_index(): Obtain the glyph index of a Unicode code point
|
||||||
Each charset is associated with a reduced character table. */
|
Returns the position of code_point in the character table of the given font,
|
||||||
enum topti_charset
|
or -1 if code_point is not part of that set.
|
||||||
{
|
@f Font object
|
||||||
charset_numeric = 0, /* 10 elements: 0..9 */
|
@code_point Unicode code point to locate the glyph for */
|
||||||
charset_upper = 1, /* 26 elements: A..Z */
|
int topti_glyph_index(font_t const *f, uint32_t code_point);
|
||||||
charset_alpha = 2, /* 52 elements: A..Z, a..z */
|
|
||||||
charset_alnum = 3, /* 62 elements: A..Z, a..z, 0..9 */
|
|
||||||
charset_print = 4, /* 95 elements: 0x20..0x7e */
|
|
||||||
charset_ascii = 5, /* 128 elements: 0x00..0x7f */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* charset_size(): Number of elements in each character set
|
|
||||||
@set Character set ID
|
|
||||||
Returns the expected number of glyphs, -1 if charset ID is invalid. */
|
|
||||||
int charset_size(enum topti_charset set);
|
|
||||||
|
|
||||||
/* charset_decode(): Translate ASCII into reduced character sets
|
|
||||||
Returns the position of [c] in the character table of the given charset, or
|
|
||||||
-1 if [c] is not part of that set.
|
|
||||||
@set Any character set
|
|
||||||
@c Character to decode */
|
|
||||||
int charset_decode(enum topti_charset set, uint c);
|
|
||||||
|
|
||||||
/* topti_offset(): Use a font index to find the location of a glyph
|
/* topti_offset(): Use a font index to find the location of a glyph
|
||||||
@f Font object
|
@f Font object
|
||||||
|
|
|
@ -16,41 +16,20 @@ font_t const *dfont(font_t const * font)
|
||||||
return old_font;
|
return old_font;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* charset_size(): Number of elements in each character set */
|
/* topti_glyph_index(): Obtain the glyph index of a Unicode code point */
|
||||||
int charset_size(enum topti_charset set)
|
int topti_glyph_index(font_t const *f, uint32_t code_point)
|
||||||
{
|
{
|
||||||
int size[] = { 10, 26, 52, 62, 95, 128 };
|
int glyph_start = 0;
|
||||||
return (uint)set < 6 ? size[set] : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* charset_decode(): Translate ASCII into reduced character sets */
|
for(int i = 0; i < f->block_count; i++)
|
||||||
int charset_decode(enum topti_charset set, uint c)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
switch(set)
|
|
||||||
{
|
{
|
||||||
case charset_numeric:
|
int diff = code_point - f->blocks[i].start;
|
||||||
x = c - '0';
|
if(diff >= 0 && diff < f->blocks[i].length)
|
||||||
return (x < 10) ? x : -1;
|
{
|
||||||
case charset_upper:
|
return glyph_start + diff;
|
||||||
x = (c - 'A') & ~0x20;
|
}
|
||||||
return (x < 26) ? x : -1;
|
|
||||||
case charset_alnum:
|
glyph_start += f->blocks[i].length;
|
||||||
x = c - '0';
|
|
||||||
if(x < 10) return x;
|
|
||||||
/* Intentional fallthrough */
|
|
||||||
case charset_alpha:
|
|
||||||
y = c & 0x20;
|
|
||||||
x = (c ^ y) - 'A';
|
|
||||||
/* Turn 32 into 26 and leave 0 as 0 */
|
|
||||||
y = y - (y >> 3) - (y >> 4);
|
|
||||||
return (x < 26) ? (x + y) : -1;
|
|
||||||
case charset_print:
|
|
||||||
x = c - 0x20;
|
|
||||||
return (x < 0x5f) ? x : -1;
|
|
||||||
case charset_ascii:
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -62,12 +41,12 @@ int topti_offset(font_t const *f, uint glyph)
|
||||||
/* Non-proportional fonts don't need an index */
|
/* Non-proportional fonts don't need an index */
|
||||||
if(!f->prop) return glyph * f->storage_size;
|
if(!f->prop) return glyph * f->storage_size;
|
||||||
|
|
||||||
uint8_t const *width = f->sized_data;
|
uint8_t const *width = f->glyph_width;
|
||||||
|
|
||||||
/* The index gives us the position of all glyphs whose IDs are mutiples
|
/* The index gives us the position of all glyphs whose IDs are
|
||||||
of 8. Start with a close one and iterate from there. */
|
multiples of 8. Start with a close one and iterate from there. */
|
||||||
uint g = glyph & ~0x7;
|
uint g = glyph & ~0x7;
|
||||||
int offset = f->index[g >> 3];
|
int offset = f->glyph_index[g >> 3];
|
||||||
|
|
||||||
/* Traverse the width array (which is in bits) while converting to
|
/* Traverse the width array (which is in bits) while converting to
|
||||||
longword size */
|
longword size */
|
||||||
|
@ -76,7 +55,7 @@ int topti_offset(font_t const *f, uint glyph)
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dsize() - get the width and height of rendered text */
|
/* dsize(): Get the width and height of rendered text */
|
||||||
void dsize(const char *str, font_t const * f, int *w, int *h)
|
void dsize(const char *str, font_t const * f, int *w, int *h)
|
||||||
{
|
{
|
||||||
if(!f) f = topti_font;
|
if(!f) f = topti_font;
|
||||||
|
@ -105,8 +84,8 @@ void dsize(const char *str, font_t const * f, int *w, int *h)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int glyph = charset_decode(f->charset, c);
|
int glyph = topti_glyph_index(f, c);
|
||||||
if(glyph > 0) width += f->sized_data[glyph] + CHAR_SPACING;
|
if(glyph >= 0) width += f->glyph_width[glyph] + CHAR_SPACING;
|
||||||
}
|
}
|
||||||
*w = width - CHAR_SPACING;
|
*w = width - CHAR_SPACING;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue