diff --git a/external/imgui.cmake b/external/imgui.cmake index 55b2cd00..0e0fb33d 100644 --- a/external/imgui.cmake +++ b/external/imgui.cmake @@ -9,6 +9,8 @@ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Gui Widgets REQUIRED) + +find_package(Freetype) set(IMGUI_SOURCES imgui/imconfig.h imgui/imgui.cpp @@ -23,6 +25,8 @@ set(IMGUI_SOURCES imgui/imconfig.h imgui/imstb_truetype.h imgui/backends/imgui_impl_opengl3.cpp imgui/backends/imgui_impl_opengl3.h + imgui/misc/freetype/imgui_freetype.cpp + imgui/misc/freetype/imgui_freetype.h imgui-backend-qt/backends/imgui_impl_qt.cpp imgui-backend-qt/backends/imgui_impl_qt.hpp) @@ -30,7 +34,10 @@ add_library(imgui STATIC ${IMGUI_SOURCES}) target_include_directories(imgui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/imgui) -target_link_libraries(imgui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) +target_compile_definitions(imgui PRIVATE IMGUI_ENABLE_FREETYPE) + +target_link_libraries(imgui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets + Freetype::Freetype) set(IMGUI_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/imgui ${CMAKE_CURRENT_SOURCE_DIR}/imgui-backend-qt diff --git a/scwx-qt/source/scwx/qt/model/imgui_context_model.cpp b/scwx-qt/source/scwx/qt/model/imgui_context_model.cpp index d90c96dc..80473e34 100644 --- a/scwx-qt/source/scwx/qt/model/imgui_context_model.cpp +++ b/scwx-qt/source/scwx/qt/model/imgui_context_model.cpp @@ -22,6 +22,7 @@ public: ~ImGuiContextModelImpl() = default; std::vector contexts_ {}; + ImFontAtlas fontAtlas_ {}; }; ImGuiContextModel::ImGuiContextModel() : @@ -86,7 +87,7 @@ ImGuiContext* ImGuiContextModel::CreateContext(const std::string& name) { static size_t nextId_ {0}; - ImGuiContext* context = ImGui::CreateContext(); + ImGuiContext* context = ImGui::CreateContext(&p->fontAtlas_); ImGui::SetCurrentContext(context); // ImGui Configuration @@ -136,6 +137,11 @@ std::vector ImGuiContextModel::contexts() const return p->contexts_; } +ImFontAtlas* ImGuiContextModel::font_atlas() +{ + return &p->fontAtlas_; +} + ImGuiContextModel& ImGuiContextModel::Instance() { static ImGuiContextModel instance_ {}; diff --git a/scwx-qt/source/scwx/qt/model/imgui_context_model.hpp b/scwx-qt/source/scwx/qt/model/imgui_context_model.hpp index c754adbd..894931c5 100644 --- a/scwx-qt/source/scwx/qt/model/imgui_context_model.hpp +++ b/scwx-qt/source/scwx/qt/model/imgui_context_model.hpp @@ -5,6 +5,7 @@ #include +struct ImFontAtlas; struct ImGuiContext; namespace scwx @@ -46,6 +47,7 @@ public: void DestroyContext(const std::string& name); std::vector contexts() const; + ImFontAtlas* font_atlas(); static ImGuiContextModel& Instance(); diff --git a/scwx-qt/source/scwx/qt/util/font.cpp b/scwx-qt/source/scwx/qt/util/font.cpp index f4e9965b..729f6898 100644 --- a/scwx-qt/source/scwx/qt/util/font.cpp +++ b/scwx-qt/source/scwx/qt/util/font.cpp @@ -1,13 +1,18 @@ // No suitable standard C++ replacement #define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING +// Disable strncpy warning +#define _CRT_SECURE_NO_WARNINGS + #include +#include #include #include #include #include +#include #include #include @@ -104,6 +109,9 @@ public: } } + void CreateImGuiFont(QFile& fontFile, + QByteArray& fontData, + std::vector fontSizes); void ParseNames(FT_Face face); const std::string resource_; @@ -116,6 +124,7 @@ public: ftgl::texture_atlas_t* atlas_; std::unordered_map glyphs_; + std::unordered_map imGuiFonts_; }; Font::Font(const std::string& resource) : @@ -240,6 +249,39 @@ GLuint Font::GenerateTexture(gl::OpenGLFunctions& gl) return p->atlas_->id; } +void FontImpl::CreateImGuiFont(QFile& fontFile, + QByteArray& fontData, + std::vector fontSizes) +{ + QFileInfo fileInfo(fontFile); + ImFontAtlas* fontAtlas = model::ImGuiContextModel::Instance().font_atlas(); + ImFontConfig fontConfig {}; + + // Do not transfer ownership of font data to ImGui, makes const_cast safe + fontConfig.FontDataOwnedByAtlas = false; + + for (size_t fontSize : fontSizes) + { + const float sizePixels = static_cast(fontSize); + + // Assign name to font + strncpy(fontConfig.Name, + std::format("{}:{}", fileInfo.fileName().toStdString(), fontSize) + .c_str(), + sizeof(fontConfig.Name)); + fontConfig.Name[sizeof(fontConfig.Name) - 1] = 0; + + // Add font to atlas + imGuiFonts_.emplace( + fontSize, + fontAtlas->AddFontFromMemoryTTF( + const_cast(static_cast(fontData.constData())), + fontData.size(), + sizePixels, + &fontConfig)); + } +} + std::shared_ptr Font::Create(const std::string& resource) { logger_->debug("Loading font file: {}", resource); @@ -265,6 +307,8 @@ std::shared_ptr Font::Create(const std::string& resource) font = std::make_shared(resource); QByteArray fontData = fontFile.readAll(); + font->p->CreateImGuiFont(fontFile, fontData, {16}); + font->p->atlas_ = ftgl::texture_atlas_new(512, 512, 1); ftgl::texture_font_t* textureFont = ftgl::texture_font_new_from_memory( font->p->atlas_, BASE_POINT_SIZE, fontData.constData(), fontData.size());