From 88cc93cdc94ffd95c76d14ddfae2e0b11eb1f320 Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Mon, 1 Apr 2019 14:12:05 +0200
Subject: [PATCH] imgui: Refactor font size, font initialization

---
 src/slic3r/GUI/GLCanvas3D.cpp   |  8 +++--
 src/slic3r/GUI/GUI_App.cpp      |  3 +-
 src/slic3r/GUI/ImGuiWrapper.cpp | 59 ++++++++++++++++++---------------
 src/slic3r/GUI/ImGuiWrapper.hpp | 19 ++++++-----
 4 files changed, 48 insertions(+), 41 deletions(-)

diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 4178dcb43..31c3717ff 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -4403,11 +4403,13 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h)
     if ((m_canvas == nullptr) && (m_context == nullptr))
         return;
 
-    wxGetApp().imgui()->set_display_size((float)w, (float)h);
+    auto *imgui = wxGetApp().imgui();
+    imgui->set_display_size((float)w, (float)h);
+    imgui->set_font_size(m_canvas->GetFont().GetPixelSize().y);
 #if ENABLE_RETINA_GL
-    wxGetApp().imgui()->set_style_scaling(m_retina_helper->get_scale_factor());
+    imgui->set_style_scaling(m_retina_helper->get_scale_factor());
 #else
-    wxGetApp().imgui()->set_style_scaling(m_canvas->GetContentScaleFactor());
+    imgui->set_style_scaling(m_canvas->GetContentScaleFactor());
 #endif
 
     // ensures that this canvas is current
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index fdb8968d3..f1a7d9263 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -81,7 +81,7 @@ IMPLEMENT_APP(GUI_App)
 GUI_App::GUI_App()
     : wxApp()
     , m_em_unit(10)
-    , m_imgui(nullptr)
+    , m_imgui(new ImGuiWrapper())
 {}
 
 bool GUI_App::OnInit()
@@ -138,7 +138,6 @@ bool GUI_App::OnInit()
     // initialize label colors and fonts
     init_label_colours();
     init_fonts();
-    m_imgui.reset(new ImGuiWrapper(m_normal_font.GetPixelSize().y));
 
     load_language();
 
diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp
index f626fa7f5..001e0b33f 100644
--- a/src/slic3r/GUI/ImGuiWrapper.cpp
+++ b/src/slic3r/GUI/ImGuiWrapper.cpp
@@ -25,9 +25,9 @@ namespace Slic3r {
 namespace GUI {
 
 
-ImGuiWrapper::ImGuiWrapper(float font_size)
+ImGuiWrapper::ImGuiWrapper()
     : m_glyph_ranges(nullptr)
-    , m_font_size(font_size)
+    , m_font_size(18.0)
     , m_font_texture(0)
     , m_style_scaling(1.0)
     , m_mouse_buttons(0)
@@ -36,7 +36,6 @@ ImGuiWrapper::ImGuiWrapper(float font_size)
 {
     ImGui::CreateContext();
 
-    init_default_font();
     init_input();
     init_style();
 
@@ -45,7 +44,7 @@ ImGuiWrapper::ImGuiWrapper(float font_size)
 
 ImGuiWrapper::~ImGuiWrapper()
 {
-    destroy_device_objects();
+    destroy_font();
     ImGui::DestroyContext();
 }
 
@@ -82,7 +81,7 @@ void ImGuiWrapper::set_language(const std::string &language)
 
     if (ranges != m_glyph_ranges) {
         m_glyph_ranges = ranges;
-        init_default_font();
+        destroy_font();
     }
 }
 
@@ -93,12 +92,20 @@ void ImGuiWrapper::set_display_size(float w, float h)
     io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
 }
 
+void ImGuiWrapper::set_font_size(float font_size)
+{
+    if (m_font_size != font_size) {
+        m_font_size = font_size;
+        destroy_font();
+    }
+}
+
 void ImGuiWrapper::set_style_scaling(float scaling)
 {
     if (!std::isnan(scaling) && !std::isinf(scaling) && scaling != m_style_scaling) {
         ImGui::GetStyle().ScaleAllSizes(scaling / m_style_scaling);
         m_style_scaling = scaling;
-        init_default_font();
+        destroy_font();
     }
 }
 
@@ -156,12 +163,15 @@ bool ImGuiWrapper::update_key_data(wxKeyEvent &evt)
 
 void ImGuiWrapper::new_frame()
 {
+    printf("ImGuiWrapper: new_frame()\n");
+
     if (m_new_frame_open) {
         return;
     }
 
-    if (m_font_texture == 0)
-        create_device_objects();
+    if (m_font_texture == 0) {
+        init_font();
+    }
 
     ImGui::NewFrame();
     m_new_frame_open = true;
@@ -254,7 +264,8 @@ void ImGuiWrapper::text(const std::string &label)
 
 void ImGuiWrapper::text(const wxString &label)
 {
-    this->text(into_u8(label).c_str());
+    auto label_utf8 = into_u8(label);
+    this->text(label_utf8.c_str());
 }
 
 bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>& options, int& selection)
@@ -282,6 +293,12 @@ bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>&
     return res;
 }
 
+ImVec2 ImGuiWrapper::calc_text_size(const wxString &text)
+{
+    auto text_utf8 = into_u8(text);
+    return ImGui::CalcTextSize(text_utf8.c_str());
+}
+
 void ImGuiWrapper::disabled_begin(bool disabled)
 {
     wxCHECK_RET(!m_disabled, "ImGUI: Unbalanced disabled_begin() call");
@@ -323,11 +340,13 @@ bool ImGuiWrapper::want_any_input() const
     return io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput;
 }
 
-void ImGuiWrapper::init_default_font()
+void ImGuiWrapper::init_font()
 {
+    printf("ImGuiWrapper: init_font()\n");
+
     const float font_size = m_font_size * m_style_scaling;
 
-    destroy_fonts_texture();
+    destroy_font();
 
     ImGuiIO& io = ImGui::GetIO();
     io.Fonts->Clear();
@@ -338,17 +357,8 @@ void ImGuiWrapper::init_default_font()
             throw std::runtime_error("ImGui: Could not load deafult font");
         }
     }
-}
 
-void ImGuiWrapper::create_device_objects()
-{
-    create_fonts_texture();
-}
-
-void ImGuiWrapper::create_fonts_texture()
-{
     // Build texture atlas
-    ImGuiIO& io = ImGui::GetIO();
     unsigned char* pixels;
     int width, height;
     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);   // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
@@ -554,14 +564,9 @@ bool ImGuiWrapper::display_initialized() const
     return io.DisplaySize.x >= 0.0f && io.DisplaySize.y >= 0.0f;
 }
 
-void ImGuiWrapper::destroy_device_objects()
+void ImGuiWrapper::destroy_font()
 {
-    destroy_fonts_texture();
-}
-
-void ImGuiWrapper::destroy_fonts_texture()
-{
-    if (m_font_texture) {
+    if (m_font_texture != 0) {
         ImGuiIO& io = ImGui::GetIO();
         io.Fonts->TexID = 0;
         glDeleteTextures(1, &m_font_texture);
diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp
index 7e022532a..476379da2 100644
--- a/src/slic3r/GUI/ImGuiWrapper.hpp
+++ b/src/slic3r/GUI/ImGuiWrapper.hpp
@@ -18,9 +18,6 @@ namespace GUI {
 
 class ImGuiWrapper
 {
-    typedef std::map<std::string, ImFont*> FontsMap;
-
-    FontsMap m_fonts;
     const ImWchar *m_glyph_ranges;
     float m_font_size;
     unsigned m_font_texture;
@@ -31,22 +28,27 @@ class ImGuiWrapper
     std::string m_clipboard_text;
 
 public:
-    ImGuiWrapper(float font_size);
+    ImGuiWrapper();
     ~ImGuiWrapper();
 
     void read_glsl_version();
 
     void set_language(const std::string &language);
     void set_display_size(float w, float h);
+    void set_font_size(float font_size);
     void set_style_scaling(float scaling);
     bool update_mouse_data(wxMouseEvent &evt);
     bool update_key_data(wxKeyEvent &evt);
 
+    float get_font_size() const { return m_font_size; }
     float get_style_scaling() const { return m_style_scaling; }
 
     void new_frame();
     void render();
 
+    float scaled(float x) const { return x * m_font_size * m_style_scaling; }
+    ImVec2 scaled_vec(float x, float y) const { return ImVec2(x * m_font_size * m_style_scaling, y * m_font_size * m_style_scaling); }
+
     void set_next_window_pos(float x, float y, int flag);
     void set_next_window_bg_alpha(float alpha);
 
@@ -64,6 +66,8 @@ public:
     void text(const wxString &label);
     bool combo(const wxString& label, const std::vector<std::string>& options, int& selection);   // Use -1 to not mark any option as selected
 
+    ImVec2 calc_text_size(const wxString &text);
+
     void disabled_begin(bool disabled);
     void disabled_end();
 
@@ -73,15 +77,12 @@ public:
     bool want_any_input() const;
 
 private:
-    void init_default_font();
-    void create_device_objects();
-    void create_fonts_texture();
+    void init_font();
     void init_input();
     void init_style();
     void render_draw_data(ImDrawData *draw_data);
     bool display_initialized() const;
-    void destroy_device_objects();
-    void destroy_fonts_texture();
+    void destroy_font();
 
     static const char* clipboard_get(void* user_data);
     static void clipboard_set(void* user_data, const char* text);