WIP - Added ImFontAtlas::RemoveFont(), fixed various leaks.

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

View file

@ -22263,6 +22263,12 @@ void ImGui::DebugNodeFont(ImFont* font)
}
if (SmallButton("Set as default"))
GetIO().FontDefault = font;
if (font->ContainerAtlas->Fonts.Size > 1 && !font->ContainerAtlas->Locked)
{
SameLine();
if (SmallButton("Remove"))
font->ContainerAtlas->RemoveFont(font);
}
// Display details
SetNextItemWidth(GetFontSize() * 8);

View file

@ -3628,10 +3628,11 @@ struct ImFontAtlas
IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed.
IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp.
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
IMGUI_API void RemoveFont(ImFont* font);
// FIXME-NEWATLAS: Clarify meaning/purpose
IMGUI_API void Clear(); // Clear all input and output.
IMGUI_API void ClearCache(); // Clear cached glyphs
IMGUI_API void Clear(); // Clear everything (input fonts, output glyphs/textures)
IMGUI_API void ClearCache(); // Clear cached glyphs and textures.
// As we are transitioning toward a new font system, we expect to obsolete those soon:
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
IMGUI_API void ClearFonts(); // [OBSOLETE] Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).

View file

@ -2481,6 +2481,8 @@ void ImTextureData::DestroyPixels()
// - ImFontAtlas::AddFontFromMemoryTTF()
// - ImFontAtlas::AddFontFromMemoryCompressedTTF()
// - ImFontAtlas::AddFontFromMemoryCompressedBase85TTF()
// - ImFontAtlas::RemoveFont()
// - ImFontAtlasBuildNotifySetFont()
//-----------------------------------------------------------------------------
// - ImFontAtlas::AddCustomRectRegular()
// - ImFontAtlas::AddCustomRectFontGlyph()
@ -2598,11 +2600,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)
@ -2646,12 +2652,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.
@ -3047,6 +3053,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
@ -3491,13 +3550,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];
@ -3511,6 +3576,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*
@ -4029,11 +4097,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;
}

View file

@ -4013,6 +4013,7 @@ IMGUI_API ImVec2i ImFontAtlasBuildGetTextureSizeEstimate(ImFontAtlas*
IMGUI_API bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src);
IMGUI_API void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFontConfig* src);
IMGUI_API void ImFontAtlasBuildDiscardFontGlyphs(ImFontAtlas* atlas, ImFont* font);
IMGUI_API void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFont* font);
IMGUI_API void ImFontAtlasBuildPreloadAllGlyphRanges(ImFontAtlas* atlas); // Legacy
IMGUI_API void ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, int* out_oversample_h, int* out_oversample_v);