diff options
Diffstat (limited to 'src/font.cpp')
| -rw-r--r-- | src/font.cpp | 159 |
1 files changed, 100 insertions, 59 deletions
diff --git a/src/font.cpp b/src/font.cpp index b24ea8f..58d5f50 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -34,9 +34,9 @@ TypeSafeInt_B(FONT_GLYPH_CHAR_FLAG); TypeSafeInt_B(FONT_RENDER_SURFACE_AREA_TYPE_FLAG); struct FontTypeData { - FontType *arr_ft; + FontType *arr_ft = nullptr; + uint64_t unused_fts = 0xFFFFFFFFFFFFFFFF; FontTypeIndex n_ft{0}; - FontTypeIndex h_ft{0}; } ftd; struct FontInstanceBufferItem { @@ -51,6 +51,8 @@ struct FontInstanceBufferItem { float padding[3]; }; +void FontType_Unload(FontTypeIndex idx); + uint32_t utf8_to_unicode(const char* str, uint32_t &out) { uint32_t i = 0; out = 0; @@ -243,10 +245,9 @@ void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInsta void FontType_Init() { FontTypeIndex fti; - ftd.h_ft = FontTypeIndex{0}; - ftd.n_ft = FontTypeIndex{5}; - ftd.arr_ft = pk_new_arr<FontType>(5); - for (FontTypeIndex_T i = 0; i < 5; ++i) { + ftd.n_ft = FontTypeIndex{8}; + ftd.arr_ft = pk_new_arr<FontType>(8); + for (FontTypeIndex_T i = 0; i < 8; ++i) { FontType *ft = &ftd.arr_ft[i]; ft->glyphs = nullptr; ft->renders = nullptr; @@ -276,9 +277,10 @@ void FontType_Init() { } void FontType_Teardown() { - FontTypeIndex i; - for (i = FontTypeIndex{0}; i < ftd.h_ft; ++i) { - FontType_Unload(i); + int i; + for (i = (int)(FontTypeIndex_T)ftd.n_ft-1; i >= 0; --i) { + if ((ftd.unused_fts & (1llu << i)) != 0) continue; + FontType_Unload(FontTypeIndex{(FontTypeIndex_T)i}); } if (ftd.arr_ft != nullptr) pk_delete_arr<FontType>(ftd.arr_ft, (FontTypeIndex_T)ftd.n_ft); } @@ -294,19 +296,43 @@ void FontType_Tick(double delta) { size_t index; FontType *ft; FontRender *fr; - for (FontTypeIndex_T i = 0; i < (FontTypeIndex_T)ftd.h_ft; ++i) { + for (FontTypeIndex_T i = 0; i < (FontTypeIndex_T)ftd.n_ft; ++i) { + + if ((ftd.unused_fts & (1llu << i)) != 0) continue; + index = 0; ft = &ftd.arr_ft[i]; - if (pkeSettings.rt.was_framebuffer_resized == false && ft->gr.should_update_instance_buffer == false) { + + for (FontRenderIndex_T k = 0; k < (FontRenderIndex_T)ft->n_render; ++k) { + if ((ft->unused_frs & (1llu << k)) != 0) continue; + fr = &ft->renders[k]; + if (fr->isMarkedForRemoval == true) { + if (fr->text.reserved > 0) { + // 2025-04-16 - JCB + // not passing a specific bucket because pk_cstr doesn't store it. + // FontType_AddStringRender requires a `pk_cstr &&`, so we are the proper owner. + // It's up to us to free it. + pk_delete_arr<char>(fr->text.val, fr->text.reserved); + } + ft->unused_frs |= (1llu << k); + new (fr) FontRender{}; + ft->gr.should_update_instance_buffer = true; + continue; + } + index += fr->n_glyphs; + } + + if (ft->isMarkedForRemoval == true) { + FontType_Unload(FontTypeIndex{i}); continue; } - // TODO specific bucket - for (FontRenderIndex_T k = 0; k < (FontRenderIndex_T)ft->h_render; ++k) { - index += ft->renders[k].n_glyphs; + if (pkeSettings.rt.was_framebuffer_resized == false && ft->gr.should_update_instance_buffer == false) { + continue; } if (index == 0) { + ft->bindings.instance_counter = index; continue; } ft->gr.should_update_instance_buffer = false; @@ -314,7 +340,8 @@ void FontType_Tick(double delta) { fibis = pk_new_arr<FontInstanceBufferItem>(index); ft->bindings.instance_counter = index; index = 0; - for (FontRenderIndex_T k = 0; k < (FontRenderIndex_T)ft->h_render; ++k) { + for (FontRenderIndex_T k = 0; k < (FontRenderIndex_T)ft->n_render; ++k) { + if ((ft->unused_frs & (1llu << k)) != 0) continue; fr = &ft->renders[k]; FontType_Inner_CalcTransforms(ft, fr, &fibis[index]); index += fr->n_glyphs; @@ -525,13 +552,14 @@ void FontType_Deserialize(std::istream &stream) { } FontType* FontType_Get(FontTypeIndex idx) { - assert(idx < ftd.h_ft); + assert((ftd.unused_fts & (1llu << FontTypeIndex_T(idx))) == 0); return &ftd.arr_ft[static_cast<FontTypeIndex_T>(idx)]; } FontType* FontType_GetByTitle(const pk_cstr title) { assert(title.val != nullptr); - for (FontTypeIndex_T i = 0; i < static_cast<FontTypeIndex_T>(ftd.h_ft); ++i) { + for (FontTypeIndex_T i = 0; i < (FontTypeIndex_T)ftd.n_ft; ++i) { + if ((ftd.unused_fts & (1llu << i)) != 0) continue; if (ftd.arr_ft[i].title.val == title.val) return &ftd.arr_ft[i]; if (strcmp(ftd.arr_ft[i].title.val, title.val) == 0) @@ -540,28 +568,40 @@ FontType* FontType_GetByTitle(const pk_cstr title) { return nullptr; } -FontType* FontType_GetFonts(FontTypeIndex &count) { - count = ftd.h_ft; +FontType* FontType_GetFonts(uint64_t &idx_unused) { + idx_unused = ftd.unused_fts; return ftd.arr_ft; } FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle, AssetHandle glyphsHandle, FontTypeMSDFSettings *msdf_settings, FontTypeSpacing *spacing) { VkResult vkResult; - pk_arr arr_vert_mem_reqs; - memset(&arr_vert_mem_reqs, 0, sizeof(pk_arr)); - arr_vert_mem_reqs.alignment = alignof(VkMemoryRequirements); - arr_vert_mem_reqs.stride = sizeof(VkMemoryRequirements); constexpr VkDeviceSize startingGlyphCount = 4; + const Asset *fontTexture = nullptr; + const Asset *glyphs = nullptr; + FontTypeIndex idx{0}; + FontTypeIndex_T idx_t; + FontType *ft; + uint16_t u; + assert(fontTextureHandle != AssetHandle_MAX); assert(glyphsHandle != AssetHandle_MAX); assert(msdf_settings != nullptr); assert(spacing != nullptr); - const Asset *fontTexture = AM_Get(fontTextureHandle); - FontTypeIndex idx = ftd.h_ft; - ftd.h_ft += FontTypeIndex{1}; - if (ftd.h_ft >= ftd.n_ft) { - ftd.n_ft += FontTypeIndex{5}; + for (u = 0; u < (FontTypeIndex_T)ftd.n_ft; ++u) { + if ((ftd.unused_fts & (1llu << u)) != 0) { + idx_t = u; + idx = FontTypeIndex{idx_t}; + ftd.unused_fts &= ~(1llu << idx_t); + break; + } + } + + if (idx >= ftd.n_ft) { + if (idx_t >= PKE_FONT_MAX_FONT_TYPES) { + throw "[font.cpp] out of font type slots"; + } + ftd.n_ft = FontTypeIndex{8}; FontType *arr = pk_new_arr<FontType>((FontTypeIndex_T)ftd.n_ft); if (idx > FontTypeIndex{0}) { memcpy(arr, ftd.arr_ft, sizeof(FontType) * (FontTypeIndex_T)idx); @@ -570,18 +610,20 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle ftd.arr_ft = arr; } - FontTypeIndex_T idx_t = (FontTypeIndex_T)idx; - FontType *ft = &ftd.arr_ft[idx_t]; + fontTexture = AM_Get(fontTextureHandle); + + idx_t = (FontTypeIndex_T)idx; + ft = &ftd.arr_ft[idx_t]; ft->title = title; ft->fontTextureAssetHandle = fontTextureHandle; ft->glyphDetailsAssetHandle = glyphsHandle; ft->renders = pk_new_arr<FontRender>(startingGlyphCount); - ft->h_render = FontRenderIndex{0}; ft->n_render = FontRenderIndex{startingGlyphCount}; + ft->unused_frs = 0xFFFFFFFFFFFFFFFF; ft->msdf_settings = *msdf_settings; ft->spacing = *spacing; - const Asset *glyphs = AM_Get(glyphsHandle); + glyphs = AM_Get(glyphsHandle); ft->n_glyphs = glyphs->size / sizeof(FontGlyphChar); ft->glyphs = (FontGlyphChar*)glyphs->ptr; @@ -708,11 +750,14 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle } void FontType_Unload(FontTypeIndex idx) { + assert((ftd.unused_fts & (1llu << (FontTypeIndex_T)idx)) == 0); + FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)idx]; // TODO specific bucket if (ft->renders != nullptr) { - for (FontRenderIndex_T i = 0; i < (FontRenderIndex_T)ft->h_render; ++i) { + for (FontRenderIndex_T i = 0; i < (FontRenderIndex_T)ft->n_render; ++i) { + if ((ft->unused_frs & (1llu << i)) != 0) continue; if (ft->renders[i].glyph_indices != nullptr) { pk_delete_arr<uint32_t>(ft->renders[i].glyph_indices, ft->renders[i].n_glyphs); } @@ -793,7 +838,8 @@ void FontType_Unload(FontTypeIndex idx) { ft->title.val = nullptr; ft->title.length = 0; } - ECS_MarkForRemoval(ft); + ftd.unused_fts |= (1llu << (FontTypeIndex_T)idx); + new (ft) FontType{}; } void FontType_cstr_to_unicode(const FontType &ft, pk_arr_t<uint32_t> &arr, const pk_cstr &str) { @@ -843,12 +889,22 @@ FontRenderHandle FontType_AddStringRender(FontTypeIndex idx_ft, const pk_cstr && FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)idx_ft]; FontRender *fr; uint32_t i, count; - FontRenderIndex idx_fr = ft->h_render; - ft->h_render += FontRenderIndex{1}; + FontRenderIndex idx_fr = FontRenderIndex{0}; - if (ft->h_render >= ft->n_render) { + for (i = 0; i < (FontRenderIndex_T)ft->n_render; ++i) { + if ((ft->unused_frs & (1llu << i)) != 0) { + ft->unused_frs &= ~(1llu << i); + idx_fr = FontRenderIndex{0}; + break; + } + } + + if (idx_fr >= ft->n_render) { + if (idx_fr >= FontRenderIndex{PKE_FONT_MAX_FONT_RENDERS}) { + throw "[font.cpp] out of FontRender slots"; + } FontRenderIndex_T old_count{static_cast<FontRenderIndex_T>(ft->n_render)}; - ft->n_render += FontRenderIndex{5}; + ft->n_render += FontRenderIndex{8}; FontRender *arr = pk_new_arr<FontRender>((FontRenderIndex_T)ft->n_render); memcpy(arr, ft->renders, sizeof(FontRender) * old_count); pk_delete_arr<FontRender>(ft->renders, old_count); @@ -890,11 +946,11 @@ FontRenderHandle FontType_AddStringRender(FontTypeIndex idx_ft, const pk_cstr && } FontRender *FontType_GetFontRender(FontRenderHandle frh) { - if (frh.index_ft >= ftd.h_ft) { + if ((ftd.unused_fts & (1llu << (FontTypeIndex_T)frh.index_ft)) != 0) { return nullptr; } FontType *ft = &ftd.arr_ft[static_cast<FontTypeIndex_T>(frh.index_ft)]; - if (frh.index_fr >= ft->h_render) { + if ((ft->unused_frs & (1llu << (FontRenderIndex_T)frh.index_fr)) != 0) { return nullptr; } return &ft->renders[static_cast<FontRenderIndex_T>(frh.index_fr)]; @@ -902,18 +958,18 @@ FontRender *FontType_GetFontRender(FontRenderHandle frh) { void FontType_UpdateStringRender(FontRenderHandle frh, FontRenderSettings *settings) { assert(settings != nullptr); - assert((FontTypeIndex_T)ftd.h_ft > (FontTypeIndex_T)frh.index_ft); + assert((ftd.unused_fts & (1llu << (FontTypeIndex_T)frh.index_ft)) == 0); FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)frh.index_ft]; - assert((FontRenderIndex_T)ft->h_render > (FontRenderIndex_T)frh.index_fr); + assert((ft->unused_frs & (1llu << (FontTypeIndex_T)frh.index_fr)) == 0); ft->gr.should_update_instance_buffer = true; ft->renders[(FontRenderIndex_T)frh.index_fr].settings = *settings; } void FontType_UpdateStringRenderText(FontRenderHandle frh, pk_cstr &&cstr) { uint32_t i, count; - assert(frh.index_ft < ftd.h_ft); + assert((ftd.unused_fts & (1llu << (FontTypeIndex_T)frh.index_ft)) == 0); FontType &ft = ftd.arr_ft[static_cast<FontTypeIndex_T>(frh.index_ft)]; - assert(frh.index_fr < ft.h_render); + assert((ft.unused_frs & (1llu << (FontTypeIndex_T)frh.index_fr)) == 0); FontRender &fr = ft.renders[static_cast<FontRenderIndex_T>(frh.index_fr)]; pk_cstr old_str = fr.text; if (window == NULL) { @@ -941,25 +997,10 @@ void FontType_UpdateStringRenderText(FontRenderHandle frh, pk_cstr &&cstr) { void FontType_RemoveStringRender(FontRenderHandle handle) { FontRender *fr; - uint32_t buffer_start_index; FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)handle.index_ft]; // hack, but works ft->gr.should_update_instance_buffer = true; fr = &ft->renders[(FontRenderIndex_T)handle.index_fr]; - ft->bindings.instance_counter -= fr->n_glyphs; - buffer_start_index = fr->buffer_start_index; - fr->n_glyphs = 0; - for (FontRenderIndex_T i = (FontRenderIndex_T)handle.index_fr + 1; FontRenderIndex{i} < ft->h_render; ++i) { - fr = &ft->renders[i]; - fr->buffer_start_index = buffer_start_index; - buffer_start_index += fr->n_glyphs; - } - if (fr->text.reserved > 0) { - // 2025-04-16 - JCB - // not passing a specific bucket because pk_cstr doesn't store it. - // font.cpp assumes the user has already cloned the string if necessary - only assigns the value. - pk_delete_arr<char>(fr->text.val, fr->text.reserved); - } ECS_MarkForRemoval(fr); } |
