From 24f7328e5f7939c0fa9d9dd8c6cf9fd06c38540a Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 Jun 2025 11:55:40 +0200 Subject: [PATCH] DrawList, Fonts: fixed ImFontAtlasTextureRepack() overwriting draw list shared data UV's etc. even when not bound. (#8694, #8465) ImFontAtlasUpdateDrawListsSharedData() call from ImFontAtlasTextureRepack() would trigger this. For simplicity we also track current atlas in ImDrawListSharedData, but we could probably use Font->ContainerAtlas. --- imgui.cpp | 10 ++++++---- imgui_draw.cpp | 18 ++++++++++-------- imgui_internal.h | 7 ++++--- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9ed61ba5d..4ace6433d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3932,7 +3932,7 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso ImGuiContext& g = *GImGui; if (mouse_cursor <= ImGuiMouseCursor_None || mouse_cursor >= ImGuiMouseCursor_COUNT) // We intentionally accept out of bound values. mouse_cursor = ImGuiMouseCursor_Arrow; - ImFontAtlas* font_atlas = g.DrawListSharedData.Font->ContainerAtlas; + ImFontAtlas* font_atlas = g.DrawListSharedData.FontAtlas; for (ImGuiViewportP* viewport : g.Viewports) { // We scale cursor with current viewport/monitor, however Windows 10 for its own hardware cursor seems to be using a different scale factor. @@ -8813,10 +8813,12 @@ void ImGui::SetCurrentFont(ImFont* font, float font_size_before_scaling, float f #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS IM_ASSERT(font->Scale > 0.0f); #endif - g.DrawListSharedData.Font = g.Font; - ImFontAtlasUpdateDrawListsSharedData(g.Font->ContainerAtlas); + ImFontAtlas* atlas = font->ContainerAtlas; + g.DrawListSharedData.FontAtlas = atlas; + g.DrawListSharedData.Font = font; + ImFontAtlasUpdateDrawListsSharedData(atlas); if (g.CurrentWindow != NULL) - g.CurrentWindow->DrawList->_SetTexture(font->ContainerAtlas->TexRef); + g.CurrentWindow->DrawList->_SetTexture(atlas->TexRef); } } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index cd3d22ef9..3621deb46 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2694,10 +2694,11 @@ void ImFontAtlas::ClearFonts() Fonts.clear_delete(); TexIsBuilt = false; for (ImDrawListSharedData* shared_data : DrawListSharedDatas) - { - shared_data->Font = NULL; - shared_data->FontScale = shared_data->FontSize = 0.0f; - } + if (shared_data->FontAtlas == this) + { + shared_data->Font = NULL; + shared_data->FontScale = shared_data->FontSize = 0.0f; + } } static void ImFontAtlasBuildUpdateRendererHasTexturesFromContext(ImFontAtlas* atlas) @@ -3914,10 +3915,11 @@ void ImFontAtlasUpdateDrawListsTextures(ImFontAtlas* atlas, ImTextureRef old_tex void ImFontAtlasUpdateDrawListsSharedData(ImFontAtlas* atlas) { for (ImDrawListSharedData* shared_data : atlas->DrawListSharedDatas) - { - shared_data->TexUvWhitePixel = atlas->TexUvWhitePixel; - shared_data->TexUvLines = atlas->TexUvLines; - } + if (shared_data->FontAtlas == atlas) + { + shared_data->TexUvWhitePixel = atlas->TexUvWhitePixel; + shared_data->TexUvLines = atlas->TexUvLines; + } } // Set current texture. This is mostly called from AddTexture() + to handle a failed resize. diff --git a/imgui_internal.h b/imgui_internal.h index fe71e49b0..b3a950c7a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -838,9 +838,10 @@ struct IMGUI_API ImDrawListSharedData { ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas (== FontAtlas->TexUvWhitePixel) const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas (== FontAtlas->TexUvLines) - ImFont* Font; // Current/default font (optional, for simplified AddText overload) - float FontSize; // Current/default font size (optional, for simplified AddText overload) - float FontScale; // Current/default font scale (== FontSize / Font->FontSize) + ImFontAtlas* FontAtlas; // Current font atlas + ImFont* Font; // Current font (used for simplified AddText overload) + float FontSize; // Current font size (used for for simplified AddText overload) + float FontScale; // Current font scale (== FontSize / Font->FontSize) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc float InitialFringeScale; // Initial scale to apply to AA fringe