summaryrefslogtreecommitdiff
path: root/src/font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/font.cpp')
-rw-r--r--src/font.cpp159
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);
}