From 98636f4a239aed1dfccbc42bd38b76756d7ac0ba Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Nov 2025 15:39:41 +0100 Subject: [PATCH] Fonts: fixed handling of `ImFontConfig::FontDataOwnedByAtlas = false` which did erroneously make a copy of the font data. (#9086) Amend 815168c7e + Added explicit casts for intent/clarity when passing to stb_truetype/freetype. --- docs/CHANGELOG.txt | 5 +++++ imgui_draw.cpp | 10 ++-------- misc/freetype/imgui_freetype.cpp | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index df9330ea2..4e1c1c1a7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,11 @@ Breaking Changes: Other Changes: +- Fonts: fixed handling of `ImFontConfig::FontDataOwnedByAtlas = false` which + did erroneously make a copy of the font data, essentially defeating the purpose + of this flag and wasting memory. + Undetected since July 2015 and now spotted by @TellowKrinkle, this is perhaps + the oldest bug in Dear ImGui history (albeit for a rarely used feature)! (#9086) - Scrollbar: fixed a codepath leading to a divide-by-zero (which would not be noticeable by user but detected by sanitizers). (#9089) [@judicaelclair] diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 589de9b91..0084dc187 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3052,12 +3052,6 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in) font->Sources.push_back(font_cfg); ImFontAtlasBuildUpdatePointers(this); // Pointers to Sources are otherwise dangling after we called Sources.push_back(). - if (font_cfg->FontDataOwnedByAtlas == false) - { - font_cfg->FontDataOwnedByAtlas = true; - font_cfg->FontData = ImMemdup(font_cfg->FontData, (size_t)font_cfg->FontDataSize); - } - // Sanity check // We don't round cfg.SizePixels yet as relative size of merged fonts are used afterwards. if (font_cfg->GlyphExcludeRanges != NULL) @@ -4583,14 +4577,14 @@ static bool ImGui_ImplStbTrueType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig* IM_ASSERT(src->FontLoaderData == NULL); // Initialize helper structure for font loading and verify that the TTF/OTF data is correct - const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)src->FontData, src->FontNo); + const int font_offset = stbtt_GetFontOffsetForIndex((const 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)) + if (!stbtt_InitFont(&bd_font_data->FontInfo, (const 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."); diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 16bb9817c..26a087017 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -174,7 +174,7 @@ struct ImGui_ImplFreeType_FontSrcBakedData bool ImGui_ImplFreeType_FontSrcData::InitFont(FT_Library ft_library, ImFontConfig* src, ImGuiFreeTypeLoaderFlags extra_font_loader_flags) { - FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)src->FontData, (FT_Long)src->FontDataSize, (FT_Long)src->FontNo, &FtFace); + FT_Error error = FT_New_Memory_Face(ft_library, (const FT_Byte*)src->FontData, (FT_Long)src->FontDataSize, (FT_Long)src->FontNo, &FtFace); if (error != 0) return false; error = FT_Select_Charmap(FtFace, FT_ENCODING_UNICODE);