Browse Source

Fonts: Added PushFontSize(), PopFontSize() api. Added font_size param to PushFont() as well.

Fonts: Fixed PopFont() recovery.

(To squash into "Added PushFontSize(), PopFontSize() api."
ocornut 7 months ago
parent
commit
daaf0e4ef3
4 changed files with 75 additions and 42 deletions
  1. 53 31
      imgui.cpp
  2. 8 6
      imgui.h
  3. 7 4
      imgui_draw.cpp
  4. 7 1
      imgui_internal.h

+ 53 - 31
imgui.cpp

@@ -1270,6 +1270,7 @@ static void             UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt);
 
 // Misc
 static void             UpdateFontsNewFrame();
+static void             UpdateFontsEndFrame();
 static void             UpdateTexturesNewFrame();
 static void             UpdateTexturesEndFrame();
 static void             UpdateSettings();
@@ -5762,6 +5763,7 @@ void ImGui::EndFrame()
     // End frame
     g.WithinFrameScope = false;
     g.FrameCountEnded = g.FrameCount;
+    UpdateFontsEndFrame();
 
     // Initiate moving window + handle left-click and right-click focus
     UpdateMouseMovingWindowEndFrame();
@@ -8579,64 +8581,84 @@ void ImGui::UpdateFontsNewFrame()
     ImFontAtlas* atlas = g.IO.Fonts;
     if ((g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) == 0)
         atlas->Locked = true;
-    SetCurrentFont(GetDefaultFont(), GetDefaultFont()->Sources[0].SizePixels);
+    PushFont(GetDefaultFont(), GetDefaultFont()->Sources[0].SizePixels);
     IM_ASSERT(g.Font->IsLoaded());
 }
 
-// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
-void ImGui::SetCurrentFont(ImFont* font, float font_size)
+void ImGui::UpdateFontsEndFrame()
 {
-    ImGuiContext& g = *GImGui;
-    IM_ASSERT(font && font->IsLoaded());    // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
-    IM_ASSERT(font->Scale > 0.0f);
-    g.Font = font;
-    //g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.FontBaked->Size * g.Font->Scale);
-    g.FontSize = font_size;// g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
-    g.FontBaked = g.Font->GetFontBaked(g.FontSize);
-    g.FontScale = g.FontSize / g.FontBaked->Size;
-    g.DrawListSharedData.Font = g.Font;
-    g.DrawListSharedData.FontSize = g.FontSize;
-    g.DrawListSharedData.FontScale = g.FontScale;
-    ImFontAtlasUpdateDrawListsSharedData(g.Font->ContainerAtlas);
-    if (g.CurrentWindow)
-        g.CurrentWindow->DrawList->_SetTexture(font->ContainerAtlas->TexRef);
-}
-
-// Use ImDrawList::_SetTextureID(), making our shared g.FontStack[] authoritative against window-local ImDrawList.
-// - Whereas ImDrawList::PushTextureID()/PopTextureID() is not to be used across Begin() calls.
+    PopFont();
+}
+
+// Use ImDrawList::_SetTexture(), making our shared g.FontStack[] authoritative against window-local ImDrawList.
+// - Whereas ImDrawList::PushTexture()/PopTexture() is not to be used across Begin() calls.
 // - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did...
 //   - Some code paths never really fully worked with multiple atlas textures.
-//   - The right-ish solution may be to remove _SetTextureID() and make AddText/RenderText lazily call PushTextureID()/PopTextureID()
+//   - The right-ish solution may be to remove _SetTexture() and make AddText/RenderText lazily call PushTexture()/PopTexture()
 //     the same way AddImage() does, but then all other primitives would also need to? I don't think we should tackle this problem
 //     because we have a concrete need and a test bed for multiple atlas textures.
 // FIXME-NEWATLAS-V2: perhaps we can now leverage ImFontAtlasUpdateDrawListsTextures() ?
-void ImGui::PushFont(ImFont* font)
+void ImGui::SetCurrentFont(ImFont* font, float font_size)
+{
+    ImGuiContext& g = *GImGui;
+    g.Font = font;
+    //g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.FontBaked->FontSize * g.Font->Scale);
+    g.FontSize = font_size;// g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
+    if (font != NULL)
+    {
+        IM_ASSERT(font && font->IsLoaded());    // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
+        IM_ASSERT(font->Scale > 0.0f);
+        g.FontBaked = g.Font->GetFontBaked(g.FontSize);
+        g.FontScale = g.FontSize / g.FontBaked->Size;
+        g.DrawListSharedData.Font = g.Font;
+        g.DrawListSharedData.FontSize = g.FontSize;
+        g.DrawListSharedData.FontScale = g.FontScale;
+        ImFontAtlasUpdateDrawListsSharedData(g.Font->ContainerAtlas);
+        if (g.CurrentWindow != NULL)
+            g.CurrentWindow->DrawList->_SetTexture(font->ContainerAtlas->TexRef);
+    }
+    else
+    {
+        g.FontBaked = NULL;
+        g.FontScale = 0.0f;
+    }
+}
+
+void ImGui::PushFont(ImFont* font, float font_size)
 {
     ImGuiContext& g = *GImGui;
     if (font == NULL)
         font = GetDefaultFont();
-    g.FontStack.push_back(font);
-    SetCurrentFont(font, g.FontSize);
+    if (font_size < 0.0f)
+        font_size = g.FontSize;
+    g.FontStack.push_back({ font, font_size });
+    SetCurrentFont(font, font_size);
 }
 
 void  ImGui::PopFont()
 {
     ImGuiContext& g = *GImGui;
-    if (g.FontStack.Size <= 0)
+    if (g.FontStack.Size <= 1 && g.WithinFrameScope)
     {
         IM_ASSERT_USER_ERROR(0, "Calling PopFont() too many times!");
         return;
     }
     g.FontStack.pop_back();
-    ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
-    SetCurrentFont(font, g.FontSize); // FIXME-BAKED: size in stack
+    if (ImFontStackData* font_stack_data = (g.FontStack.Size > 0) ? &g.FontStack.back() : NULL)
+        SetCurrentFont(font_stack_data->Font, font_stack_data->FontSize);
+    else
+        SetCurrentFont(NULL, 0.0f);
 }
 
-void    ImGui::SetFontSize(float size)
+void    ImGui::PushFontSize(float font_size)
 {
-    // FIXME-BAKED
     ImGuiContext& g = *GImGui;
-    SetCurrentFont(g.Font, size);
+    PushFont(g.Font, font_size);
+}
+
+void    ImGui::PopFontSize()
+{
+    PopFont();
 }
 
 //-----------------------------------------------------------------------------

+ 8 - 6
imgui.h

@@ -469,11 +469,13 @@ namespace ImGui
     IMGUI_API void          SetScrollFromPosX(float local_x, float center_x_ratio = 0.5f);  // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position.
     IMGUI_API void          SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f);  // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position.
 
-    // Parameters stacks (shared)
-    IMGUI_API void          PushFont(ImFont* font);                                         // use NULL as a shortcut to push default font
+    // Parameters stacks (font)
+    IMGUI_API void          PushFont(ImFont* font, float font_size = -1);                   // use NULL as a shortcut to push default font. Use <0.0f to keep current font size.
     IMGUI_API void          PopFont();
-    IMGUI_API void          SetFontSize(float size);
-    //IMGUI_API void          PopFontSize();
+    IMGUI_API void          PushFontSize(float size);
+    IMGUI_API void          PopFontSize();
+
+    // Parameters stacks (shared)
     IMGUI_API void          PushStyleColor(ImGuiCol idx, ImU32 col);                        // modify a style color. always use this if you modify the style after NewFrame().
     IMGUI_API void          PushStyleColor(ImGuiCol idx, const ImVec4& col);
     IMGUI_API void          PopStyleColor(int count = 1);
@@ -3657,8 +3659,8 @@ struct ImFontBaked
 // Font runtime data and rendering
 // - ImFontAtlas automatically loads a default embedded font for you if you didn't load one manually.
 // - Since 1.92.X a font may be rendered as any size! Therefore a font doesn't have one specific size.
-// - Use 'font->GetBakedForSize(size)' to retrieve the ImFontBaked* corresponding to a given size.
-// - If you used g.Font + g.FontSize (which is frequent from the ImGui layer), you can use g.FontBaked as a shortcut, as g.FontBaked == g.Font->GetBakedForSize(g.FontSize).
+// - Use 'font->GetFontBaked(size)' to retrieve the ImFontBaked* corresponding to a given size.
+// - If you used g.Font + g.FontSize (which is frequent from the ImGui layer), you can use g.FontBaked as a shortcut, as g.FontBaked == g.Font->GetFontBaked(g.FontSize).
 struct ImFont
 {
     // [Internal] Members: Cold ~32/40/80 bytes

+ 7 - 4
imgui_draw.cpp

@@ -434,7 +434,7 @@ void ImDrawList::_SetDrawListSharedData(ImDrawListSharedData* data)
 }
 
 // Initialize before use in a new frame. We always have a command ready in the buffer.
-// In the majority of cases, you would want to call PushClipRect() and PushTextureID() after this.
+// In the majority of cases, you would want to call PushClipRect() and PushTexture() after this.
 void ImDrawList::_ResetForNewFrame()
 {
     // Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
@@ -683,7 +683,7 @@ void ImDrawList::PopTexture()
     _OnChangedTexture();
 }
 
-// This is used by ImGui::PushFont()/PopFont(). It works because we never use _TextureIdStack[] elsewhere than in PushTextureID()/PopTextureID().
+// This is used by ImGui::PushFont()/PopFont(). It works because we never use _TextureIdStack[] elsewhere than in PushTexture()/PopTexture().
 void ImDrawList::_SetTexture(ImTextureRef tex_ref)
 {
     if (_CmdHeader.TexRef == tex_ref)
@@ -3042,7 +3042,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
     if (font_cfg.SizePixels <= 0.0f)
         font_cfg.SizePixels = 13.0f * 1.0f;
     if (font_cfg.Name[0] == '\0')
-        ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels);
+        ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf");
     font_cfg.EllipsisChar = (ImWchar)0x0085;
     font_cfg.GlyphOffset.y = 1.0f * IM_TRUNC(font_cfg.SizePixels / 13.0f);  // Add +1 offset per 13 units
 
@@ -3074,7 +3074,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
         // Store a short copy of filename into into the font name for convenience
         const char* p;
         for (p = filename + ImStrlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {}
-        ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels);
+        ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s", p);
     }
     return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges);
 }
@@ -3137,6 +3137,9 @@ static void ImFontAtlasBuildNotifySetFont(ImFontAtlas* atlas, ImFont* old_font,
                 if (need_bind_ctx)
                     ImGui::SetCurrentContext(curr_ctx);
             }
+            for (ImFontStackData& font_stack_data : ctx->FontStack)
+                if (font_stack_data.Font == old_font)
+                    font_stack_data.Font = new_font;
         }
     }
 }

+ 7 - 1
imgui_internal.h

@@ -869,6 +869,12 @@ struct ImDrawDataBuilder
     ImDrawDataBuilder()                     { memset(this, 0, sizeof(*this)); }
 };
 
+struct ImFontStackData
+{
+    ImFont*     Font;
+    float       FontSize;
+};
+
 //-----------------------------------------------------------------------------
 // [SECTION] Style support
 //-----------------------------------------------------------------------------
@@ -2237,7 +2243,7 @@ struct ImGuiContext
     ImGuiCol                        DebugFlashStyleColorIdx;    // (Keep close to ColorStack to share cache line)
     ImVector<ImGuiColorMod>         ColorStack;                 // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
     ImVector<ImGuiStyleMod>         StyleVarStack;              // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin()
-    ImVector<ImFont*>               FontStack;                  // Stack for PushFont()/PopFont() - inherited by Begin()
+    ImVector<ImFontStackData>       FontStack;                  // Stack for PushFont()/PopFont() - inherited by Begin()
     ImVector<ImGuiFocusScopeData>   FocusScopeStack;            // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin()
     ImVector<ImGuiItemFlags>        ItemFlagsStack;             // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin()
     ImVector<ImGuiGroupData>        GroupStack;                 // Stack for BeginGroup()/EndGroup() - not inherited by Begin()