diff --git a/src/draw.c b/src/draw.c index 490e240a..58505ac9 100644 --- a/src/draw.c +++ b/src/draw.c @@ -275,24 +275,18 @@ void draw_text_ex(struct renderer_canvas *canvas, struct font *font, struct v2 p struct v2 draw_pos = pos; draw_pos.y += font->point_size * scale; - for (u64 i = 0; i < str.len; ++i) { - u8 c = str.text[i]; + struct string_codepoint_iter iter = string_codepoint_iter_begin(str); + while (string_codepoint_iter_next(&iter)) { + u32 codepoint = iter.codepoint; /* TODO: Remove this (placeholder \n) */ - if (c == '\n') { + if (codepoint == '\n') { draw_pos.x = pos.x; draw_pos.y += (font->point_size * 1.5f) * scale; continue; } - struct font_glyph *glyph = font_get_glyph(font, c); - if (!glyph) { - glyph = font_get_glyph(font, (u8)'?'); - if (!glyph) { - continue; - } - } - + struct font_glyph *glyph = font_get_glyph(font, codepoint); f32 x = draw_pos.x + glyph->off_x * scale; f32 y = draw_pos.y + glyph->off_y * scale; f32 width = glyph->width * scale; @@ -315,4 +309,5 @@ void draw_text_ex(struct renderer_canvas *canvas, struct font *font, struct v2 p draw_pos.x += glyph->advance * scale; } + string_codepoint_iter_end(&iter); } diff --git a/src/font.c b/src/font.c index b815536a..3745ab4a 100644 --- a/src/font.c +++ b/src/font.c @@ -9,9 +9,12 @@ #include "string.h" #include "renderer.h" -#define FONT_CHARS " !\"#$%&\'()-.,*/0123456789:;<=+>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" #define LOOKUP_TABLE_SIZE (256) +GLOBAL u32 g_font_codes[] = { + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF +}; + struct font_task_params { struct font_task_params *next_free; @@ -111,11 +114,11 @@ INTERNAL WORK_TASK_FUNC_DEF(font_load_asset_task, vparams) FMT_STR(path))); } - struct string font_chars = STR(FONT_CHARS); + ASSERT(ARRAY_COUNT(g_font_codes) < LOOKUP_TABLE_SIZE); /* Decode */ struct resource res = resource_open(path); - struct ttf_decode_result result = ttf_decode(scratch.arena, res.bytes, point_size, font_chars); + struct ttf_decode_result result = ttf_decode(scratch.arena, res.bytes, point_size, g_font_codes, ARRAY_COUNT(g_font_codes)); resource_close(res); /* Send texture to GPU */ @@ -150,9 +153,9 @@ INTERNAL WORK_TASK_FUNC_DEF(font_load_asset_task, vparams) MEMCPY(font->glyphs, result.glyphs, sizeof(*font->glyphs) * result.glyphs_count); /* Build lookup table */ - for (u64 i = 0; i < font_chars.len; ++i) { - u8 c = font_chars.text[i]; - font->lookup[c] = result.cache_indices[i]; + for (u64 i = 0; i < ARRAY_COUNT(g_font_codes); ++i) { + u32 codepoint = g_font_codes[i]; + font->lookup[codepoint] = result.cache_indices[i]; } font_task_params_release(params); @@ -227,14 +230,13 @@ struct font *font_load(struct string path, f32 point_size) * Other * ========================== */ -struct font_glyph *font_get_glyph(struct font *font, u8 c) +struct font_glyph *font_get_glyph(struct font *font, u32 codepoint) { - /* Need to add a check here for c < LOOKUP_TABLE_SIZE if range is ever increased */ - CT_ASSERT(sizeof(c) == 1 && LOOKUP_TABLE_SIZE >= 256); - - u16 index = font->lookup[c]; - if (index < font->glyphs_count) { - return &font->glyphs[index]; + if (codepoint < LOOKUP_TABLE_SIZE) { + u16 index = font->lookup[codepoint]; + if (index < font->glyphs_count) { + return &font->glyphs[index]; + } } return &font->glyphs[0]; } diff --git a/src/font.h b/src/font.h index 445eea9c..3757f99f 100644 --- a/src/font.h +++ b/src/font.h @@ -40,6 +40,6 @@ struct asset *font_load_asset(struct string path, f32 point_size, b32 help); struct font *font_load_async(struct string path, f32 point_size); struct font *font_load(struct string path, f32 point_size); -struct font_glyph *font_get_glyph(struct font *font, u8 c); +struct font_glyph *font_get_glyph(struct font *font, u32 codepoint); #endif diff --git a/src/string.c b/src/string.c index d7b5ac91..498479fc 100644 --- a/src/string.c +++ b/src/string.c @@ -467,6 +467,32 @@ struct string _string_format(struct arena *arena, struct string fmt, ...) * Unicode * ========================== */ +struct string_codepoint_iter string_codepoint_iter_begin(struct string str) +{ + return (struct string_codepoint_iter) { + .src = str + }; +} + +b32 string_codepoint_iter_next(struct string_codepoint_iter *iter) +{ + if (iter->pos < iter->src.len) { + struct string str_remaining = { .len = (iter->src.len - iter->pos), .text = iter->src.text + iter->pos }; + struct utf8_decode_result decoded = utf8_decode(str_remaining); + iter->pos += decoded.advance8; + iter->codepoint = decoded.codepoint; + return true; + } else { + return false; + } +} + +void string_codepoint_iter_end(struct string_codepoint_iter *iter) +{ + /* Do nothing */ + (UNUSED)iter; +} + /* utf8 <- utf16 */ struct string string_from_string16(struct arena *arena, struct string16 str16) { diff --git a/src/string.h b/src/string.h index f31b25b3..1c09a035 100644 --- a/src/string.h +++ b/src/string.h @@ -84,8 +84,21 @@ struct string string_formatv(struct arena *arena, struct string fmt, va_list arg * Unicode * ========================== */ +struct string_codepoint_iter { + u32 codepoint; + + /* Internal */ + struct string src; + u64 pos; +}; + +struct string_codepoint_iter string_codepoint_iter_begin(struct string str); +b32 string_codepoint_iter_next(struct string_codepoint_iter *iter); +void string_codepoint_iter_end(struct string_codepoint_iter *iter); + struct string string_from_string16(struct arena *arena, struct string16 str16); struct string string_from_string32(struct arena *arena, struct string32 str32); + struct string16 string16_from_string(struct arena *arena, struct string str8); struct string32 string32_from_string(struct arena *arena, struct string str8); diff --git a/src/ttf.h b/src/ttf.h index e779eacb..92843484 100644 --- a/src/ttf.h +++ b/src/ttf.h @@ -14,6 +14,6 @@ struct ttf_decode_result { struct ttf_startup_receipt { i32 _; }; struct ttf_startup_receipt ttf_startup(void); -struct ttf_decode_result ttf_decode(struct arena *arena, struct buffer encoded, f32 point_size, struct string cache_chars); +struct ttf_decode_result ttf_decode(struct arena *arena, struct buffer encoded, f32 point_size, u32 *cache_codes, u32 cache_codes_count); #endif diff --git a/src/ttf_dwrite.cpp b/src/ttf_dwrite.cpp index 0fcf2f26..edc49b61 100644 --- a/src/ttf_dwrite.cpp +++ b/src/ttf_dwrite.cpp @@ -68,7 +68,7 @@ struct ttf_startup_receipt ttf_startup(void) return (struct ttf_startup_receipt) { 0 }; } -struct ttf_decode_result ttf_decode(struct arena *arena, struct buffer encoded, f32 point_size, struct string cache_chars) +struct ttf_decode_result ttf_decode(struct arena *arena, struct buffer encoded, f32 point_size, u32 *cache_codes, u32 cache_codes_count) { COLORREF bg_color = RGB(0,0,0); COLORREF fg_color = RGB(255,255,255); @@ -274,12 +274,9 @@ struct ttf_decode_result ttf_decode(struct arena *arena, struct buffer encoded, /* Construct indices array */ u16 *cache_indices = NULL; - if (cache_chars.len > 0) { - struct temp_arena scratch = scratch_begin(arena); - cache_indices = arena_push_array_zero(arena, u16, cache_chars.len); - struct string32 str32 = string32_from_string(scratch.arena, cache_chars); - font_face->GetGlyphIndicesA(str32.text, (u32)str32.len, cache_indices); - scratch_end(scratch); + if (cache_codes_count > 0) { + cache_indices = arena_push_array_zero(arena, u16, cache_codes_count); + font_face->GetGlyphIndices(cache_codes, cache_codes_count, cache_indices); } /* Release */