diff --git a/src/rdpq/rdpq_font.c b/src/rdpq/rdpq_font.c index 6d11b6ef71..c0923b773e 100644 --- a/src/rdpq/rdpq_font.c +++ b/src/rdpq/rdpq_font.c @@ -17,8 +17,7 @@ #include "rdpq_internal.h" #include "asset.h" #include "fmath.h" - -#define UNLIKELY(x) __builtin_expect(!!(x), 0) +#include "utils.h" #define MAX_STYLES 256 @@ -106,12 +105,13 @@ rdpq_font_t* rdpq_font_load_buf(void *buf, int sz) assertf(sz >= sizeof(rdpq_font_t), "Font buffer too small (sz=%d)", sz); assertf(memcmp(fnt->magic, FONT_MAGIC_LOADED, 3), "Trying to load already loaded font data (buf=%p, sz=%08x)", buf, sz); assertf(!memcmp(fnt->magic, FONT_MAGIC, 3), "invalid font data (magic: %c%c%c)", fnt->magic[0], fnt->magic[1], fnt->magic[2]); - assertf(fnt->version == 5, "unsupported font version: %d\nPlease regenerate fonts with an updated mkfont tool", fnt->version); + assertf(fnt->version == 6, "unsupported font version: %d\nPlease regenerate fonts with an updated mkfont tool", fnt->version); fnt->ranges = PTR_DECODE(fnt, fnt->ranges); fnt->glyphs = PTR_DECODE(fnt, fnt->glyphs); fnt->atlases = PTR_DECODE(fnt, fnt->atlases); fnt->kerning = PTR_DECODE(fnt, fnt->kerning); - fnt->styles = PTR_DECODE(fnt, fnt->styles); + fnt->styles = &fnt->builtin_style; + fnt->num_styles = 1; for (int i = 0; i < fnt->num_atlases; i++) { void *buf = PTR_DECODE(fnt, fnt->atlases[i].sprite); fnt->atlases[i].sprite = sprite_load_buf(buf, fnt->atlases[i].size); @@ -175,17 +175,21 @@ static void font_unload(rdpq_font_t *fnt) rspq_block_free(fnt->atlases[i].up); fnt->atlases[i].up = NULL; fnt->atlases[i].sprite = PTR_ENCODE(fnt, fnt->atlases[i].sprite); } - for (int i = 0; i < MAX_STYLES; i++) { + for (int i = 0; i < fnt->num_styles; i++) { if (fnt->styles[i].block) { rspq_block_free(fnt->styles[i].block); fnt->styles[i].block = NULL; } } + if (fnt->num_styles > 1) { + free(fnt->styles); + fnt->styles = &fnt->builtin_style; + fnt->num_styles = 1; + } fnt->ranges = PTR_ENCODE(fnt, fnt->ranges); fnt->glyphs = PTR_ENCODE(fnt, fnt->glyphs); fnt->atlases = PTR_ENCODE(fnt, fnt->atlases); fnt->kerning = PTR_ENCODE(fnt, fnt->kerning); - fnt->styles = PTR_ENCODE(fnt, fnt->styles); memcpy(fnt->magic, FONT_MAGIC, 3); } @@ -240,8 +244,22 @@ float __rdpq_font_kerning(const rdpq_font_t *fnt, int16_t glyph1, int16_t glyph2 void rdpq_font_style(rdpq_font_t *fnt, uint8_t style_id, const rdpq_fontstyle_t *style) { - // NOTE: fnt->num_styles refer to how many styles have been defined at - // mkfont time. The font always contain room for 256 styles (all zeroed). + if (style_id >= fnt->num_styles) { + assertf(style_id < MAX_STYLES, "style_id %d exceeds maximum %d", style_id, MAX_STYLES); + + if (fnt->num_styles == 1) { + fnt->num_styles = 16; + fnt->styles = calloc(16, sizeof(style_t)); + memcpy(&fnt->styles[0], &fnt->builtin_style, sizeof(style_t)); + fnt->builtin_style.block = NULL; + } else { + int old_styles = fnt->num_styles; + fnt->num_styles = MAX(fnt->num_styles*2, MAX_STYLES); + fnt->styles = realloc(fnt->styles, fnt->num_styles * sizeof(style_t)); + memset(&fnt->styles[old_styles], 0, (fnt->num_styles - old_styles) * sizeof(style_t)); + } + } + style_t *s = &fnt->styles[style_id]; s->color = style->color; s->outline_color = style->outline_color; @@ -258,7 +276,8 @@ int rdpq_font_render_paragraph(const rdpq_font_t *fnt, const rdpq_paragraph_char while (ch->font_id == font_id) { const glyph_t *g = &fnt->glyphs[ch->glyph]; if (UNLIKELY(ch->style_id != cur_style)) { - assertf(fnt->styles[ch->style_id].block, "style %d not defined in this font", ch->style_id); + assertf(ch->style_id < fnt->num_styles && fnt->styles[ch->style_id].block, + "style %d not defined in this font", ch->style_id); rspq_block_run(fnt->styles[ch->style_id].block); cur_style = ch->style_id; } diff --git a/src/rdpq/rdpq_font_internal.h b/src/rdpq/rdpq_font_internal.h index 291b831286..429e34cfae 100644 --- a/src/rdpq/rdpq_font_internal.h +++ b/src/rdpq/rdpq_font_internal.h @@ -87,6 +87,7 @@ typedef struct rdpq_font_s { uint32_t num_atlases; ///< Number of atlases in the font uint32_t num_kerning; ///< Number of kerning pairs in the font uint32_t num_styles; ///< Number of styles in the font + style_t builtin_style; ///< Default style for the font range_t *ranges; ///< Array of ranges glyph_t *glyphs; ///< Array of glyphs atlas_t *atlases; ///< Array of atlases diff --git a/tools/mkfont/mkfont_out.cpp b/tools/mkfont/mkfont_out.cpp index d5900f672d..f1a7457fe9 100644 --- a/tools/mkfont/mkfont_out.cpp +++ b/tools/mkfont/mkfont_out.cpp @@ -302,7 +302,7 @@ struct Font { outfn = fn; fnt = (rdpq_font_t*)calloc(1, sizeof(rdpq_font_t)); memcpy(fnt->magic, FONT_MAGIC, 3); - fnt->version = 5; + fnt->version = 6; fnt->flags = FONT_TYPE_ALIASED; fnt->point_size = point_size; fnt->ascent = ascent; @@ -365,7 +365,13 @@ void Font::write() w32(out, fnt->num_glyphs); w32(out, fnt->num_atlases); w32(out, fnt->num_kerning); - w32(out, 1); // num styles (not supported by mkfont yet) + // Write builtin style + w32(out, 1); // num styles + uint32_t offset_builtin_style = ftell(out); + w32(out, 0xFFFFFFFF); // color + w32(out, 0x40404040); // outline + w32(out, 0); // runtime pointer + int off_placeholders = ftell(out); w32(out, (uint32_t)0); // placeholder w32(out, (uint32_t)0); // placeholder @@ -432,26 +438,13 @@ void Font::write() } uint32_t offset_end = ftell(out); - // Write styles - walign(out, 16); - uint32_t offset_styles = ftell(out); - w32(out, 0xFFFFFFFF); // color - w32(out, 0x40404040); // outline - w32(out, 0); // runtime pointer - for (int i=0; i<255; i++) - { - w32(out, 0); // color - w32(out, 0); // outline - w32(out, 0); // runtime pointer - } - // Write offsets fseek(out, off_placeholders, SEEK_SET); w32(out, offset_ranges); w32(out, offset_glypes); w32(out, offset_atlases); w32(out, offset_kernings); - w32(out, offset_styles); + w32(out, offset_builtin_style); fseek(out, offset_end, SEEK_SET);