Fonts: added ImFontAtlas::RemoveFont(), fixed various leaks.

This commit is contained in:
ocornut
2024-12-19 16:21:07 +01:00
parent df8450d928
commit cec3e945f0
4 changed files with 84 additions and 6 deletions

View File

@@ -2476,6 +2476,8 @@ void ImTextureData::DestroyPixels()
// - ImFontAtlas::AddFontFromMemoryTTF()
// - ImFontAtlas::AddFontFromMemoryCompressedTTF()
// - ImFontAtlas::AddFontFromMemoryCompressedBase85TTF()
// - ImFontAtlas::RemoveFont()
// - ImFontAtlasBuildNotifySetFont()
//-----------------------------------------------------------------------------
// - ImFontAtlas::AddCustomRectRegular()
// - ImFontAtlas::AddCustomRectFontGlyph()
@@ -2593,11 +2595,15 @@ void ImFontAtlas::ClearInputData()
{
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
for (ImFontConfig& font_cfg : Sources)
{
if (FontLoader && FontLoader->FontSrcDestroy != NULL)
FontLoader->FontSrcDestroy(this, &font_cfg);
if (font_cfg.FontData && font_cfg.FontDataOwnedByAtlas)
{
IM_FREE(font_cfg.FontData);
font_cfg.FontData = NULL;
}
}
// When clearing this we lose access to the font name and other information used to build the font.
for (ImFont* font : Fonts)
@@ -2641,12 +2647,12 @@ void ImFontAtlas::ClearFonts()
void ImFontAtlas::Clear()
{
//IM_DELETE(Builder); // FIXME-NEW-ATLAS: Clarify ClearXXX functions
const ImFontLoader* font_loader = FontLoader;
ImFontAtlasBuildSetupFontLoader(this, NULL);
//const ImFontLoader* font_loader = FontLoader;
//ImFontAtlasBuildSetupFontLoader(this, NULL);
ClearInputData();
ClearTexData();
ClearFonts();
ImFontAtlasBuildSetupFontLoader(this, font_loader);
//ImFontAtlasBuildSetupFontLoader(this, font_loader);
}
// FIXME-NEWATLAS: Too widespread purpose. Clarify each call site in current WIP demo.
@@ -3041,6 +3047,59 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed
return font;
}
// We allow old_font == new_font which forces updating all values (e.g. sizes)
static void ImFontAtlasBuildNotifySetFont(ImFontAtlas* atlas, ImFont* old_font, ImFont* new_font)
{
if (ImDrawListSharedData* shared_data = atlas->DrawListSharedData)
{
if (shared_data->Font == old_font)
shared_data->Font = new_font;
if (ImGuiContext* ctx = shared_data->Context)
{
if (ctx->IO.FontDefault == old_font)
ctx->IO.FontDefault = new_font;
if (ctx->Font == old_font)
{
ImGuiContext* curr_ctx = ImGui::GetCurrentContext();
bool need_bind_ctx = ctx != curr_ctx;
if (need_bind_ctx)
ImGui::SetCurrentContext(ctx);
ImGui::SetCurrentFont(new_font);
if (need_bind_ctx)
ImGui::SetCurrentContext(curr_ctx);
}
}
}
}
void ImFontAtlas::RemoveFont(ImFont* font)
{
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
ImFontAtlasBuildDiscardFontGlyphs(this, font);
for (int src_n = 0; src_n < font->SourcesCount; src_n++)
{
ImFontConfig* src = (ImFontConfig*)(void*)&font->Sources[src_n];
if (FontLoader && FontLoader->FontSrcDestroy != NULL)
FontLoader->FontSrcDestroy(this, src);
if (src->FontData != NULL && src->FontDataOwnedByAtlas)
IM_FREE(src->FontData);
}
bool removed = Fonts.find_erase(font);
IM_ASSERT(removed);
Sources.erase(font->Sources, font->Sources + font->SourcesCount);
ImFontAtlasBuildUpdatePointers(this);
font->ContainerAtlas = NULL;
IM_DELETE(font);
// Notify external systems
ImFont* new_current_font = Fonts.empty() ? NULL : Fonts[0];
ImFontAtlasBuildNotifySetFont(this, font, new_current_font);
}
// FIXME-NEWATLAS-V1: Feature is broken for now.
/*
// Register custom rectangle glyphs
@@ -3485,13 +3544,19 @@ void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFontConfig* sr
font->LockSingleSrcConfigIdx = -1;
}
void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFont* font)
void ImFontAtlasBuildDiscardFontGlyphs(ImFontAtlas* atlas, ImFont* font)
{
for (ImFontGlyph& glyph : font->Glyphs)
if (glyph.PackId >= 0)
ImFontAtlasPackDiscardRect(atlas, glyph.PackId);
font->BuildClearGlyphs();
font->FallbackChar = font->EllipsisChar = 0;
}
// Discard old glyphs and reload font. Use if changing font size.
void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFont* font)
{
ImFontAtlasBuildDiscardFontGlyphs(atlas, font);
for (int src_n = 0; src_n < font->SourcesCount; src_n++)
{
ImFontConfig* src = (ImFontConfig*)(void*)&font->Sources[src_n];
@@ -3505,6 +3570,9 @@ void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFont* font)
ImFontAtlasBuildSetupFontSpecialGlyphs(atlas, src); // Technically this is called for each source sub-font, tho 99.9% of the time the first one fills everything.
}
// Notify external systems
ImFontAtlasBuildNotifySetFont(atlas, font, font);
}
// Those functions are designed to facilitate changing the underlying structures for ImFontAtlas to store an array of ImDrawListSharedData*
@@ -4023,11 +4091,13 @@ static bool ImGui_ImplStbTrueType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig*
const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)src->FontData, src->FontNo);
if (font_offset < 0)
{
IM_DELETE(bd_font_data);
IM_ASSERT_USER_ERROR(0, "stbtt_GetFontOffsetForIndex(): FontData is incorrect, or FontNo cannot be found.");
return false;
}
if (!stbtt_InitFont(&bd_font_data->FontInfo, (unsigned char*)src->FontData, font_offset))
{
IM_DELETE(bd_font_data);
IM_ASSERT_USER_ERROR(0, "stbtt_InitFont(): failed to parse FontData. It is correct and complete? Check FontDataSize.");
return false;
}