diff --git a/src/app/app_core.c b/src/app/app_core.c index 6b591da8..826c35f5 100644 --- a/src/app/app_core.c +++ b/src/app/app_core.c @@ -241,7 +241,7 @@ void P_AppStartup(String args_str) N_StartupReceipt host_sr = host_startup(); AC_StartupReceipt asset_cache_sr = AC_Startup(); TTF_StartupReceipt ttf_sr = ttf_startup(); - F_StartupReceipt font_sr = font_startup(&asset_cache_sr, &ttf_sr); + F_StartupReceipt font_sr = F_Startup(&asset_cache_sr, &ttf_sr); S_StartupReceipt sprite_sr = sprite_startup(); M_StartupReceipt mixer_sr = mixer_startup(); SND_StartupReceipt sound_sr = sound_startup(&asset_cache_sr); diff --git a/src/draw/draw_core.c b/src/draw/draw_core.c index 4a8bea37..da825295 100644 --- a/src/draw/draw_core.c +++ b/src/draw/draw_core.c @@ -347,7 +347,7 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params) { D_TextGlyph *tg = PushStruct(scratch.arena, D_TextGlyph); ++num_line_glyphs; - F_Glyph *glyph = font_get_glyph(params.font, codepoint); + F_Glyph *glyph = F_GetGlyph(params.font, codepoint); tg->off_x = glyph->off_x * params.scale; tg->off_y = glyph->off_y * params.scale; tg->width = glyph->width * params.scale; diff --git a/src/font/font_core.c b/src/font/font_core.c index b988655c..864ae77b 100644 --- a/src/font/font_core.c +++ b/src/font/font_core.c @@ -1,83 +1,75 @@ -#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 -}; +F_SharedState F_shared_state = ZI; -struct font_task_params { - struct font_task_params *next_free; +//////////////////////////////// +//~ Startup - AC_Asset *asset; - f32 point_size; - u64 path_len; - char path_cstr[1024]; -}; - -struct font_task_params_store { - struct font_task_params *head_free; - Arena *arena; - P_Mutex mutex; -}; - -/* ========================== * - * Global state - * ========================== */ - -Global struct { - struct font_task_params_store params; -} G = ZI, DebugAlias(G, G_font); - -/* ========================== * - * Startup - * ========================== */ - -F_StartupReceipt font_startup(AC_StartupReceipt *asset_cache_sr, - TTF_StartupReceipt *ttf_sr) +F_StartupReceipt F_Startup(AC_StartupReceipt *asset_cache_sr, TTF_StartupReceipt *ttf_sr) { __prof; + F_SharedState *g = &F_shared_state; (UNUSED)asset_cache_sr; (UNUSED)ttf_sr; - G.params.arena = AllocArena(Gibi(64)); + g->params.arena = AllocArena(Gibi(64)); return (F_StartupReceipt) { 0 }; } -/* ========================== * - * Load task param store - * ========================== */ +//////////////////////////////// +//~ Load job -internal struct font_task_params *font_task_params_alloc(void) +F_LoadJobSig *F_AllocJobSig(void) { - struct font_task_params *p = 0; + F_SharedState *g = &F_shared_state; + F_LoadJobSig *p = 0; { - P_Lock lock = P_LockE(&G.params.mutex); - if (G.params.head_free) { - p = G.params.head_free; - G.params.head_free = p->next_free; - } else { - p = PushStruct(G.params.arena, struct font_task_params); + P_Lock lock = P_LockE(&g->params.mutex); + if (g->params.head_free) + { + p = g->params.head_free; + g->params.head_free = p->next_free; + } + else + { + p = PushStruct(g->params.arena, F_LoadJobSig); } P_Unlock(&lock); } return p; } -internal void font_task_params_release(struct font_task_params *p) +void F_ReleaseJobSig(F_LoadJobSig *p) { - P_Lock lock = P_LockE(&G.params.mutex); - p->next_free = G.params.head_free; - G.params.head_free = p; + F_SharedState *g = &F_shared_state; + P_Lock lock = P_LockE(&g->params.mutex); + p->next_free = g->params.head_free; + g->params.head_free = p; P_Unlock(&lock); } -/* ========================== * - * Load - * ========================== */ - -internal P_JobDef(font_load_asset_job, job) +P_JobDef(F_LoadAssetJob, job) { __prof; TempArena scratch = BeginScratchNoConflict(); - struct font_task_params *params = job.sig; + Readonly LocalPersist u32 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 + }; + + F_LoadJobSig *params = job.sig; String path = STRING(params->path_len, (u8 *)params->path_cstr); f32 point_size = params->point_size; AC_Asset *asset = params->asset; @@ -86,17 +78,18 @@ internal P_JobDef(font_load_asset_job, job) i64 start_ns = P_TimeNs(); Assert(StringEndsWith(path, Lit(".ttf"))); - Assert(countof(g_font_codes) < LOOKUP_TABLE_SIZE); + Assert(countof(font_codes) < F_LookupTableSize); /* Decode */ R_Resource res = resource_open(path); - if (!resource_exists(&res)) { + if (!resource_exists(&res)) + { /* FIME: Load baked font instead of panicking */ P_Panic(StringFormat(scratch.arena, - Lit("Font \"%F\" not found"), - FmtString(path))); + Lit("Font \"%F\" not found"), + FmtString(path))); } - TTF_Result result = ttf_decode(scratch.arena, resource_get_data(&res), point_size, g_font_codes, countof(g_font_codes)); + TTF_Result result = ttf_decode(scratch.arena, resource_get_data(&res), point_size, font_codes, countof(font_codes)); resource_close(&res); /* Send texture to GPU */ @@ -108,7 +101,7 @@ internal P_JobDef(font_load_asset_job, job) AC_Store store = AC_OpenStore(); font = PushStruct(store.arena, F_Font); font->glyphs = PushStructsNoZero(store.arena, F_Glyph, result.glyphs_count); - font->lookup = PushStructs(store.arena, u16, LOOKUP_TABLE_SIZE); + font->lookup = PushStructs(store.arena, u16, F_LookupTableSize); AC_CloseStore(&store); } @@ -120,10 +113,11 @@ internal P_JobDef(font_load_asset_job, job) font->point_size = point_size; /* FIXME: Load baked font instead of panicking */ - if (font->glyphs_count <= 0) { + if (font->glyphs_count <= 0) + { P_Panic(StringFormat(scratch.arena, - Lit("Parsed 0 glyphs from font \"%F\"!"), - FmtString(path))); + Lit("Parsed 0 glyphs from font \"%F\"!"), + FmtString(path))); } /* CopyStruct glyphs from decode result */ @@ -131,12 +125,13 @@ internal P_JobDef(font_load_asset_job, job) CopyBytes(font->glyphs, result.glyphs, sizeof(*font->glyphs) * result.glyphs_count); /* Build lookup table */ - for (u64 i = 0; i < countof(g_font_codes); ++i) { - u32 codepoint = g_font_codes[i]; + for (u64 i = 0; i < countof(font_codes); ++i) + { + u32 codepoint = font_codes[i]; font->lookup[codepoint] = result.cache_indices[i]; } - font_task_params_release(params); + F_ReleaseJobSig(params); P_LogSuccessF("Loaded font \"%F\" (point size %F) in %F seconds", FmtString(path), FmtFloat((f64)point_size), FmtFloat(SecondsFromNs(P_TimeNs() - start_ns))); AC_MarkReady(asset, font); @@ -144,28 +139,33 @@ internal P_JobDef(font_load_asset_job, job) EndScratch(scratch); } +//////////////////////////////// +//~ Load + /* Returns the asset from the asset cache */ -AC_Asset *font_load_asset(String path, f32 point_size, b32 wait) +AC_Asset *F_LoadAsset(String path, f32 point_size, b32 wait) { __prof; TempArena scratch = BeginScratchNoConflict(); /* Concatenate point_size to path for key */ String key = StringFormat(scratch.arena, - Lit("%F%F_font"), - FmtString(path), - FmtFloatP((f64)point_size, 1)); + Lit("%F%F_font"), + FmtString(path), + FmtFloatP((f64)point_size, 1)); u64 hash = AC_HashFromKey(key); b32 is_first_touch; AC_Asset *asset = AC_TouchCache(key, hash, &is_first_touch); - if (is_first_touch) { + if (is_first_touch) + { /* Assemble task params */ - struct font_task_params *params = font_task_params_alloc(); - if (path.len > (sizeof(params->path_cstr) - 1)) { + F_LoadJobSig *params = F_AllocJobSig(); + if (path.len > (sizeof(params->path_cstr) - 1)) + { P_Panic(StringFormat(scratch.arena, - Lit("Font path \"%F\" too long!"), - FmtString(path))); + Lit("Font path \"%F\" too long!"), + FmtString(path))); } CstrBuffFromStringToBuff(StringFromArray(params->path_cstr), path); params->path_len = path.len; @@ -174,8 +174,9 @@ AC_Asset *font_load_asset(String path, f32 point_size, b32 wait) /* PushStruct task */ AC_MarkLoading(asset); - P_Run(1, font_load_asset_job, params, P_Pool_Background, P_Priority_Low, 0); - if (wait) { + P_Run(1, F_LoadAssetJob, params, P_Pool_Background, P_Priority_Low, 0); + if (wait) + { AC_WaitOnAssetReady(asset); } } @@ -184,38 +185,42 @@ AC_Asset *font_load_asset(String path, f32 point_size, b32 wait) return asset; } -F_Font *font_load_async(String path, f32 point_size) +F_Font *F_LoadFontAsync(String path, f32 point_size) { __prof; - AC_Asset *asset = font_load_asset(path, point_size, 0); + AC_Asset *asset = F_LoadAsset(path, point_size, 0); F_Font *f = (F_Font *)AC_DataFromStore(asset); return f; } -F_Font *font_load(String path, f32 point_size) +F_Font *F_LoadFontWait(String path, f32 point_size) { __prof; - AC_Asset *asset = font_load_asset(path, point_size, 1); + AC_Asset *asset = F_LoadAsset(path, point_size, 1); AC_WaitOnAssetReady(asset); F_Font *f = (F_Font *)AC_DataFromStore(asset); return f; } -/* ========================== * - * Other - * ========================== */ +//////////////////////////////// +//~ Get glyph -F_Glyph *font_get_glyph(F_Font *font, u32 codepoint) +F_Glyph *F_GetGlyph(F_Font *font, u32 codepoint) { - if (codepoint < LOOKUP_TABLE_SIZE) { + if (codepoint < F_LookupTableSize) + { u16 index = font->lookup[codepoint]; - if (index < font->glyphs_count) { + if (index < font->glyphs_count) + { return &font->glyphs[index]; } } - if (codepoint == '?') { + if (codepoint == '?') + { return &font->glyphs[font->lookup[0]]; - } else { + } + else + { return &font->glyphs[font->lookup['?']]; } } diff --git a/src/font/font_core.h b/src/font/font_core.h index 3b77f3e9..f42cde34 100644 --- a/src/font/font_core.h +++ b/src/font/font_core.h @@ -1,3 +1,6 @@ +//////////////////////////////// +//~ Font types + Struct(F_Glyph) { f32 off_x; f32 off_y; @@ -17,11 +20,60 @@ Struct(F_Font) { u16 *lookup; }; +//////////////////////////////// +//~ Font job types + +Struct(F_LoadJobSig) +{ + F_LoadJobSig *next_free; + + AC_Asset *asset; + f32 point_size; + u64 path_len; + char path_cstr[1024]; +}; + +Struct(F_LoadJobSigStore) +{ + F_LoadJobSig *head_free; + Arena *arena; + P_Mutex mutex; +}; + +/* ========================== * + * Global state + * ========================== */ + +#define F_LookupTableSize (256) + +Struct(F_SharedState) +{ + F_LoadJobSigStore params; +}; + +extern F_SharedState F_shared_state; + +//////////////////////////////// +//~ Startup + Struct(F_StartupReceipt) { i32 _; }; -F_StartupReceipt font_startup(AC_StartupReceipt *asset_cache_sr, TTF_StartupReceipt *ttf_sr); +F_StartupReceipt F_Startup(AC_StartupReceipt *asset_cache_sr, TTF_StartupReceipt *ttf_sr); -AC_Asset *font_load_asset(String path, f32 point_size, b32 wait); -F_Font *font_load_async(String path, f32 point_size); -F_Font *font_load(String path, f32 point_size); +//////////////////////////////// +//~ Font load job -F_Glyph *font_get_glyph(F_Font *font, u32 codepoint); +F_LoadJobSig *F_AllocJobSig(void); +void F_ReleaseJobSig(F_LoadJobSig *p); +P_JobDef(F_LoadAssetJob, job); + +//////////////////////////////// +//~ Font load operations + +AC_Asset *F_LoadAsset(String path, f32 point_size, b32 wait); +F_Font *F_LoadFontAsync(String path, f32 point_size); +F_Font *F_LoadFontWait(String path, f32 point_size); + +//////////////////////////////// +//~ Font data operations + +F_Glyph *F_GetGlyph(F_Font *font, u32 codepoint); diff --git a/src/user/user_core.c b/src/user/user_core.c index 1c272138..924d6aee 100644 --- a/src/user/user_core.c +++ b/src/user/user_core.c @@ -447,7 +447,7 @@ internal void draw_debug_console(i32 level, b32 minimized) G.console_logs_height = 0; i64 now_ns = P_TimeNs(); - F_Font *font = font_load_async(Lit("font/fixedsys.ttf"), 12.0f); + F_Font *font = F_LoadFontAsync(Lit("font/fixedsys.ttf"), 12.0f); if (font) { P_Lock lock = P_LockE(&G.console_logs_mutex); { @@ -1436,7 +1436,7 @@ internal void user_update(P_Window *window) #if 0 /* Draw contact info */ { - F_Font *disp_font = font_load_async(Lit("font/fixedsys.ttf"), 12.0f); + F_Font *disp_font = F_LoadFontAsync(Lit("font/fixedsys.ttf"), 12.0f); if (disp_font) { f32 offset_px = 10; @@ -1553,7 +1553,7 @@ internal void user_update(P_Window *window) #if 0 /* Test info */ { - F_Font *disp_font = font_load_async(Lit("font/fixedsys.ttf"), 12.0f); + F_Font *disp_font = F_LoadFontAsync(Lit("font/fixedsys.ttf"), 12.0f); if (disp_font) { f32 offset_px = 10; String fmt = Lit( @@ -1902,7 +1902,7 @@ internal void user_update(P_Window *window) Ent *ent = hovered_ent; Vec2 pos = AddVec2(G.ui_cursor, VEC2(15, 15)); - F_Font *font = font_load_async(Lit("font/fixedsys.ttf"), 12.0f); + F_Font *font = F_LoadFontAsync(Lit("font/fixedsys.ttf"), 12.0f); if (font) { TempArena temp = BeginTempArena(scratch.arena); @@ -1927,7 +1927,7 @@ internal void user_update(P_Window *window) if (G.debug_draw) { __profn("Draw debug info"); - F_Font *font = font_load_async(Lit("font/fixedsys.ttf"), 12.0f); + F_Font *font = F_LoadFontAsync(Lit("font/fixedsys.ttf"), 12.0f); if (font) { TempArena temp = BeginTempArena(scratch.arena); String text = ZI;