Quellcode durchsuchen

Fonts: added ImGuiStyle::FontSizeBase. Ensuring PushFontSize() works before main loop and across NewFrame().

# Conflicts:
#	imgui.cpp
ocornut vor 2 Monaten
Ursprung
Commit
1e118ab891
5 geänderte Dateien mit 125 neuen und 56 gelöschten Zeilen
  1. 74 32
      imgui.cpp
  2. 16 4
      imgui.h
  3. 29 15
      imgui_demo.cpp
  4. 1 1
      imgui_draw.cpp
  5. 5 4
      imgui_internal.h

+ 74 - 32
imgui.cpp

@@ -1354,6 +1354,7 @@ static void*                GImAllocatorUserData = NULL;
 
 ImGuiStyle::ImGuiStyle()
 {
+    FontSizeBase                = 0.0f;             // Will default to io.Fonts->Fonts[0] on first frame.
     Alpha                       = 1.0f;             // Global alpha applies to everything in Dear ImGui.
     DisabledAlpha               = 0.60f;            // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha.
     WindowPadding               = ImVec2(8,8);      // Padding within a window
@@ -1415,6 +1416,10 @@ ImGuiStyle::ImGuiStyle()
     HoverFlagsForTooltipMouse   = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_AllowWhenDisabled;    // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse.
     HoverFlagsForTooltipNav     = ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_AllowWhenDisabled;  // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
 
+    // [Internal]
+    _MainScale                  = 1.0f;
+    _NextFrameFontSizeBase      = 0.0f;
+
     // Default theme
     ImGui::StyleColorsDark(this);
 }
@@ -1423,6 +1428,8 @@ ImGuiStyle::ImGuiStyle()
 // Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times.
 void ImGuiStyle::ScaleAllSizes(float scale_factor)
 {
+    _MainScale *= scale_factor;
+    FontSizeBase = ImTrunc(FontSizeBase * scale_factor);
     WindowPadding = ImTrunc(WindowPadding * scale_factor);
     WindowRounding = ImTrunc(WindowRounding * scale_factor);
     WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
@@ -4403,7 +4410,7 @@ static void SetCurrentWindow(ImGuiWindow* window)
             ImGuiViewport* viewport = window->Viewport;
             g.FontRasterizerDensity = (viewport->FramebufferScale.x != 0.0f) ? viewport->FramebufferScale.x : g.IO.DisplayFramebufferScale.x; // == SetFontRasterizerDensity()
         }
-        ImGui::UpdateCurrentFontSize();
+        ImGui::UpdateCurrentFontSize(0.0f);
         ImGui::NavUpdateCurrentWindowIsScrollPushableX();
     }
 }
@@ -8450,7 +8457,7 @@ void ImGui::SetWindowFontScale(float scale)
     IM_ASSERT(scale > 0.0f);
     ImGuiWindow* window = GetCurrentWindow();
     window->FontWindowScale = scale;
-    UpdateCurrentFontSize();
+    UpdateCurrentFontSize(0.0f);
 }
 
 void ImGui::PushFocusScope(ImGuiID id)
@@ -8619,12 +8626,24 @@ void ImGui::UpdateFontsNewFrame()
         for (ImFontAtlas* atlas : g.FontAtlases)
             atlas->Locked = true;
 
-    // We do this really unusual thing of calling *push_front()*, the reason behind that we want to support the PushFont()/NewFrame()/PopFont() idiom.
-    ImFontStackData font_stack_data = { ImGui::GetDefaultFont(), ImGui::GetDefaultFont()->LegacySize };
-    g.FontStack.push_front(font_stack_data);
-    if (g.FontStack.Size == 1)
-        ImGui::SetCurrentFont(font_stack_data.Font, font_stack_data.FontSize);
+    if (g.Style._NextFrameFontSizeBase != 0.0f)
+    {
+        g.Style.FontSizeBase = g.Style._NextFrameFontSizeBase;
+        g.Style._NextFrameFontSizeBase = 0.0f;
+    }
+
+    // Apply default font size the first time
+    ImFont* font = ImGui::GetDefaultFont();
+    if (g.Style.FontSizeBase <= 0.0f)
+        g.Style.FontSizeBase = font->LegacySize * g.Style._MainScale;
 
+    // Set initial font
+    g.Font = font;
+    g.FontSizeBeforeScaling = g.Style.FontSizeBase;
+    g.FontSize = 0.0f;
+    ImFontStackData font_stack_data = { font, g.Style.FontSizeBase, g.Style.FontSizeBase };           // <--- Will restore FontSize
+    SetCurrentFont(font_stack_data.Font, font_stack_data.FontSizeBeforeScaling, 0.0f); // <--- but use 0.0f to enable scale
+    g.FontStack.push_back(font_stack_data);
     IM_ASSERT(g.Font->IsLoaded());
 }
 
@@ -8633,6 +8652,15 @@ void ImGui::UpdateFontsEndFrame()
     PopFont();
 }
 
+ImFont* ImGui::GetDefaultFont()
+{
+    ImGuiContext& g = *GImGui;
+    ImFontAtlas* atlas = g.IO.Fonts;
+    if (atlas->Builder == NULL)
+        ImFontAtlasBuildMain(atlas);
+    return g.IO.FontDefault ? g.IO.FontDefault : atlas->Fonts[0];
+}
+
 void ImGui::RegisterUserTexture(ImTextureData* tex)
 {
     ImGuiContext& g = *GImGui;
@@ -8673,12 +8701,12 @@ void ImGui::UnregisterFontAtlas(ImFontAtlas* atlas)
 //     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::SetCurrentFont(ImFont* font, float font_size)
+void ImGui::SetCurrentFont(ImFont* font, float font_size_before_scaling, float font_size_after_scaling)
 {
     ImGuiContext& g = *GImGui;
     g.Font = font;
-    g.FontSizeBeforeScaling = font_size;
-    UpdateCurrentFontSize();
+    g.FontSizeBeforeScaling = font_size_before_scaling;
+    UpdateCurrentFontSize(font_size_after_scaling);
 
     if (font != NULL)
     {
@@ -8693,20 +8721,27 @@ void ImGui::SetCurrentFont(ImFont* font, float font_size)
     }
 }
 
-void ImGui::UpdateCurrentFontSize()
+void ImGui::UpdateCurrentFontSize(float restore_font_size_after_scaling)
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
+
+    g.Style.FontSizeBase = g.FontSizeBeforeScaling;
     if (window != NULL && window->SkipItems)
         return;
 
-    float final_size = g.FontSizeBeforeScaling * g.IO.FontGlobalScale;
+    // Restoring is pretty much only used by PopFont()/PopFontSize()
+    float final_size = (restore_font_size_after_scaling > 0.0f) ? restore_font_size_after_scaling : 0.0f;
+    if (final_size == 0.0f)
+    {
+        final_size = g.FontSizeBeforeScaling * g.IO.FontGlobalScale;
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
-    if (g.Font != NULL)
-        final_size *= g.Font->Scale;
+        if (g.Font != NULL)
+          final_size *= g.Font->Scale;
 #endif
-    if (window != NULL)
-        final_size *= window->FontWindowScale;
+        if (window != NULL)
+            final_size *= window->FontWindowScale;
+    }
 
     // Round font size
     // - We started rounding in 1.90 WIP (18991) as our layout system currently doesn't support non-rounded font size well yet.
@@ -8731,12 +8766,16 @@ void ImGui::SetFontRasterizerDensity(float rasterizer_density)
     if (g.FontRasterizerDensity == rasterizer_density)
         return;
     g.FontRasterizerDensity = rasterizer_density;
-    UpdateCurrentFontSize();
+    UpdateCurrentFontSize(0.0f);
 }
 
+// If you want to scale an existing font size:
+// - Use e.g. PushFontSize(style.FontSizeBase * factor) (= value before external scale factors applied).
+// - Do NOT use PushFontSize(GetFontSize() * factor) (= value after external scale factors applied).
 void ImGui::PushFont(ImFont* font, float font_size)
 {
     ImGuiContext& g = *GImGui;
+    g.FontStack.push_back({ g.Font, g.FontSizeBeforeScaling, g.FontSize });
     if (font == NULL)
         font = GetDefaultFont();
     if (font_size <= 0.0f)
@@ -8746,23 +8785,20 @@ void ImGui::PushFont(ImFont* font, float font_size)
         else
             font_size = g.FontSizeBeforeScaling; // Keep current font size
     }
-    g.FontStack.push_back({ font, font_size });
-    SetCurrentFont(font, font_size);
+    SetCurrentFont(font, font_size, 0.0f);
 }
 
 void  ImGui::PopFont()
 {
     ImGuiContext& g = *GImGui;
-    if (g.FontStack.Size <= 1 && g.WithinFrameScope)
+    if (g.FontStack.Size <= 0 && g.WithinFrameScope)
     {
         IM_ASSERT_USER_ERROR(0, "Calling PopFont() too many times!");
         return;
     }
+    ImFontStackData* font_stack_data = &g.FontStack.back();
+    SetCurrentFont(font_stack_data->Font, font_stack_data->FontSizeBeforeScaling, font_stack_data->FontSizeAfterScaling);
     g.FontStack.pop_back();
-    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::PushFontSize(float font_size)
@@ -15751,10 +15787,11 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
 {
     ImGuiContext& g = *GImGui;
     ImGuiIO& io = g.IO;
+    ImGuiStyle& style = g.Style;
 
     Text("Read "); SameLine(0, 0);
     TextLinkOpenURL("https://www.dearimgui.com/faq/"); SameLine(0, 0);
-    Text(" for details on font loading.");
+    Text(" for details.");
 
     SeparatorText("Backend Support for Dynamic Fonts");
     BeginDisabled();
@@ -15762,11 +15799,16 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
     EndDisabled();
 
     BeginDisabled((io.BackendFlags & ImGuiBackendFlags_RendererHasTextures) == 0);
-    SetNextItemWidth(GetFontSize() * 5);
-    DragFloat("io.FontGlobalScale", &io.FontGlobalScale, 0.05f, 0.5f, 5.0f);
-    BulletText("This is scaling font only. General scaling will come later.");
-    BulletText("Load an actual font that's not the default for best result!");
-    BulletText("Please submit feedback:"); SameLine(); TextLinkOpenURL("https://github.com/ocornut/imgui/issues/8465");
+    SetNextItemWidth(GetFontSize() * 10);
+    if (DragFloat("FontSizeBase", &style.FontSizeBase, 0.20f, 5.0f, 100.0f, "%.0f"))
+        style._NextFrameFontSizeBase = style.FontSizeBase; // FIXME: Temporary hack until we finish remaining work.
+    SameLine(0.0f, 0.0f); Text(" (out %.2f)", GetFontSize());
+    SameLine(); MetricsHelpMarker("- This is scaling font only. General scaling will come later.");
+    SetNextItemWidth(GetFontSize() * 10);
+    DragFloat("io.FontGlobalScale", &io.FontGlobalScale, 0.05f, 0.5f, 5.0f); // <-- This works, but no need to make it too visible.
+    BulletText("Load a nice font for better results!");
+    BulletText("Please submit feedback:");
+    SameLine(); TextLinkOpenURL("#8465", "https://github.com/ocornut/imgui/issues/8465");
     EndDisabled();
 
     SeparatorText("Fonts");
@@ -15786,7 +15828,7 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
 #else
         BeginDisabled();
         RadioButton("stb_truetype", false);
-        SetItemTooltip("Requires IMGUI_ENABLE_STB_TRUETYPE");
+        SetItemTooltip("Requires #define IMGUI_ENABLE_STB_TRUETYPE");
         EndDisabled();
 #endif
         SameLine();
@@ -15810,7 +15852,7 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
 #else
         BeginDisabled();
         RadioButton("FreeType", false);
-        SetItemTooltip("Requires IMGUI_ENABLE_FREETYPE + imgui_freetype.cpp.");
+        SetItemTooltip("Requires #define IMGUI_ENABLE_FREETYPE + imgui_freetype.cpp.");
         EndDisabled();
 #endif
         EndDisabled();

+ 16 - 4
imgui.h

@@ -498,8 +498,13 @@ namespace ImGui
     // *IMPORTANT* before 1.92, fonts had a single size. They can now be dynamically be adjusted.
     // - Before 1.92: PushFont() always used font default size.
     // -  Since 1.92: PushFont() preserve the current shared font size.
-    // - To use old behavior (single size font): use 'PushFont(font, font->LegacySize)' in call site, or set 'ImFontConfig::Flags |= ImFontFlags_DefaultToLegacySize' before calling AddFont().
-    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. Use font->LegacySize to revert to font size specified by AddFont().
+    // - To use old behavior (single size font, size specified in AddFontXXX() call:
+    //   - Use 'PushFont(font, font->LegacySize)' at call site
+    //   - Or set 'ImFontConfig::Flags |= ImFontFlags_DefaultToLegacySize' before calling AddFont(), and then 'PushFont(font)' will use this size.
+    // *IMPORTANT* If you want to scale an existing font size:
+    //   - OK: PushFontSize(style.FontSizeBase * factor) (= value before external scale factors applied).
+    //   - KO: PushFontSize(GetFontSize() * factor)      (= value after external scale factors applied. external scale factors are io.FontGlobalScale and per-viewport scales.).
+    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          PushFontSize(float font_size);
     IMGUI_API void          PopFontSize();
@@ -2222,6 +2227,8 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
 
 struct ImGuiStyle
 {
+    float       FontSizeBase;               // Current base font size (scaling applied). Use PushFont()/PushFontSize() to modify. Use ImGui::GetFontSize() to obtain scaled value.
+
     float       Alpha;                      // Global alpha applies to everything in Dear ImGui.
     float       DisabledAlpha;              // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha.
     ImVec2      WindowPadding;              // Padding within a window.
@@ -2287,8 +2294,13 @@ struct ImGuiStyle
     ImGuiHoveredFlags HoverFlagsForTooltipMouse;// Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse.
     ImGuiHoveredFlags HoverFlagsForTooltipNav;  // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
 
-    IMGUI_API ImGuiStyle();
-    IMGUI_API void ScaleAllSizes(float scale_factor);
+    // [Internal]
+    float       _MainScale;                 // FIXME-WIP: Reference scale, as applied by ScaleAllSizes().
+    float       _NextFrameFontSizeBase;     // FIXME: Temporary hack until we finish remaining work.
+
+    // Functions
+    IMGUI_API   ImGuiStyle();
+    IMGUI_API   void ScaleAllSizes(float scale_factor);
 
     // Obsolete names
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS

+ 29 - 15
imgui_demo.cpp

@@ -430,16 +430,25 @@ void ImGui::ShowDemoWindow(bool* p_open)
     ImGui::Text("dear imgui says hello! (%s) (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
     ImGui::Spacing();
 
-    ImGui::SeparatorText("dynamic_fonts branch");
-    ImGui::SetNextItemWidth(ImGui::GetFontSize() * 5);
-    ImGui::DragFloat("io.FontGlobalScale", &ImGui::GetIO().FontGlobalScale, 0.05f, 0.5f, 5.0f);
-    ImGui::BulletText("This is scaling font only. General scaling will come later.");
-    ImGui::BulletText("Load an actual font that's not the default for best result!");
-    ImGui::BulletText("See 'Widgets->Fonts' below for more..");
-    ImGui::BulletText("Current font loader: '%s'", ImGui::GetIO().Fonts->FontLoaderName);
-    ImGui::BulletText("Please submit feedback:"); ImGui::SameLine();
-    ImGui::TextLinkOpenURL("https://github.com/ocornut/imgui/issues/8465");
-    ImGui::Spacing();
+    {
+        ImGui::SeparatorText("dynamic_fonts branch");
+        ImGuiStyle& style = ImGui::GetStyle();
+        ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
+        ImGui::ShowFontSelector("Font");
+        ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
+        if (ImGui::DragFloat("FontSizeBase", &style.FontSizeBase, 0.20f, 5.0f, 100.0f, "%.0f"))
+            style._NextFrameFontSizeBase = style.FontSizeBase; // FIXME: Temporary hack until we finish remaining work.
+        ImGui::SameLine(0.0f, 0.0f); Text(" (out %.2f)", ImGui::GetFontSize());
+        ImGui::SameLine(); HelpMarker("- This is scaling font only. General scaling will come later.");
+        //ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
+        //ImGui::DragFloat("FontGlobalScale", &ImGui::GetIO().FontGlobalScale, 0.05f, 0.5f, 5.0f);
+        ImGui::BulletText("Load a nice font for better results!");
+        ImGui::BulletText("See 'Widgets->Fonts' below for more.");
+        //ImGui::BulletText("Current font loader: '%s'", ImGui::GetIO().Fonts->FontLoaderName);
+        ImGui::BulletText("Please submit feedback:"); ImGui::SameLine();
+        ImGui::TextLinkOpenURL("#8465", "https://github.com/ocornut/imgui/issues/8465");
+        ImGui::Spacing();
+    }
 
     IMGUI_DEMO_MARKER("Help");
     if (ImGui::CollapsingHeader("Help"))
@@ -8207,11 +8216,16 @@ void ImGui::ShowFontSelector(const char* label)
         ImGui::EndCombo();
     }
     ImGui::SameLine();
-    HelpMarker(
-        "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
-        "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
-        "- Read FAQ and docs/FONTS.md for more details.\n"
-        "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
+    if (io.BackendFlags & ImGuiBackendFlags_RendererHasTextures)
+        HelpMarker(
+            "- Load additional fonts with io.Fonts->AddFontXXX() functions.\n"
+            "- Read FAQ and docs/FONTS.md for more details.");
+    else
+        HelpMarker(
+            "- Load additional fonts with io.Fonts->AddFontXXX() functions.\n"
+            "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
+            "- Read FAQ and docs/FONTS.md for more details.\n"
+            "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
 }
 
 // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.

+ 1 - 1
imgui_draw.cpp

@@ -3190,7 +3190,7 @@ static void ImFontAtlasBuildNotifySetFont(ImFontAtlas* atlas, ImFont* old_font,
                 bool need_bind_ctx = ctx != curr_ctx;
                 if (need_bind_ctx)
                     ImGui::SetCurrentContext(ctx);
-                ImGui::SetCurrentFont(new_font, ctx->FontSize);
+                ImGui::SetCurrentFont(new_font, ctx->FontSizeBeforeScaling, ctx->FontSize);
                 if (need_bind_ctx)
                     ImGui::SetCurrentContext(curr_ctx);
             }

+ 5 - 4
imgui_internal.h

@@ -871,7 +871,8 @@ struct ImDrawDataBuilder
 struct ImFontStackData
 {
     ImFont*     Font;
-    float       FontSize;
+    float       FontSizeBeforeScaling;
+    float       FontSizeAfterScaling;
 };
 
 //-----------------------------------------------------------------------------
@@ -3116,12 +3117,12 @@ namespace ImGui
     IMGUI_API void          UnregisterUserTexture(ImTextureData* tex);
     IMGUI_API void          RegisterFontAtlas(ImFontAtlas* atlas);
     IMGUI_API void          UnregisterFontAtlas(ImFontAtlas* atlas);
-    IMGUI_API void          SetCurrentFont(ImFont* font, float font_size);
+    IMGUI_API void          SetCurrentFont(ImFont* font, float font_size_before_scaling, float font_size_after_scaling);
+    IMGUI_API void          UpdateCurrentFontSize(float restore_font_size_after_scaling);
     IMGUI_API void          SetFontRasterizerDensity(float rasterizer_density);
     inline float            GetFontRasterizerDensity() { return GImGui->FontRasterizerDensity; }
-    IMGUI_API void          UpdateCurrentFontSize();
     inline float            GetRoundedFontSize(float size) { return IM_ROUND(size); }
-    inline ImFont*          GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
+    IMGUI_API ImFont*       GetDefaultFont();
     IMGUI_API void          PushPasswordFont();
     IMGUI_API void          PopPasswordFont();
     inline ImDrawList*      GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches.