From 41a0e991f0ea621b93cfe3672a274147a5457a72 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 6 Mar 2025 20:34:18 +0100 Subject: [PATCH] Fonts: Added UI to edit FreeType loader flags. Added ImFontAtlasBuildReloadAll() / ImFontAtlasBuildReloadFont() --- imgui.cpp | 26 +++++++++++++++++++++++--- imgui_draw.cpp | 22 +++++++++++++++++++--- imgui_internal.h | 5 ++++- misc/freetype/imgui_freetype.cpp | 18 +++++++++++++++++- misc/freetype/imgui_freetype.h | 3 +++ 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 466ab28c7..1d1ad8650 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15639,7 +15639,7 @@ static void MetricsHelpMarker(const char* desc) } #ifdef IMGUI_ENABLE_FREETYPE -namespace ImGuiFreeType { IMGUI_API const ImFontLoader* GetFontLoader(); } +namespace ImGuiFreeType { IMGUI_API const ImFontLoader* GetFontLoader(); IMGUI_API bool DebugEditFontBuilderFlags(unsigned int* p_font_builder_flags); } #endif // [DEBUG] List fonts in a font atlas and display its texture @@ -15682,6 +15682,12 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas) const ImFontLoader* loader_freetype = ImGuiFreeType::GetFontLoader(); if (RadioButton("FreeType", loader_current == loader_freetype)) ImFontAtlasBuildSetupFontLoader(atlas, loader_freetype); + if (loader_current == loader_freetype) + { + Text("Shared FreeType Loader Flags:"); + if (ImGuiFreeType::DebugEditFontBuilderFlags(&atlas->FontBuilderFlags)) + ImFontAtlasBuildReloadAll(atlas); + } #else BeginDisabled(); RadioButton("FreeType", false); @@ -16585,10 +16591,24 @@ void ImGui::DebugNodeFont(ImFont* font) char c_str[5]; Text("Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar); Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar); + for (int src_n = 0; src_n < font->SourcesCount; src_n++) if (ImFontConfig* src = &font->Sources[src_n]) - BulletText("Input %d: \'%s\', Oversample: %d,%d, PixelSnapH: %d, Offset: (%.1f,%.1f)", - src_n, src->Name, src->OversampleH, src->OversampleV, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y); + if (TreeNode(src, "Input %d: \'%s\', Oversample: %d,%d, PixelSnapH: %d, Offset: (%.1f,%.1f)", + src_n, src->Name, src->OversampleH, src->OversampleV, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y)) + { + const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader; + Text("Loader: '%s'", loader->Name ? loader->Name : "N/A"); +#ifdef IMGUI_ENABLE_FREETYPE + if (loader->Name != NULL && strcmp(loader->Name, "FreeType") == 0) + { + Text("FreeType Loader Flags: 0x%08X", src->FontBuilderFlags); + if (ImGuiFreeType::DebugEditFontBuilderFlags(&src->FontBuilderFlags)) + ImFontAtlasBuildReloadFont(atlas, src); + } +#endif + TreePop(); + } // Display all glyphs of the fonts in separate pages of 256 characters for (int baked_n = 0; baked_n < atlas->Builder->BakedPool.Size; baked_n++) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 04a00c422..c7418cfca 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2519,7 +2519,7 @@ void ImTextureData::DestroyPixels() // - ImFontAtlasBuildDiscardBakes() // - ImFontAtlasBuildDiscardFontBakedGlyph() // - ImFontAtlasBuildDiscardFontBaked() -// - ImFontAtlasBuildDiscardFont() +// - ImFontAtlasBuildDiscardFontBakes() //----------------------------------------------------------------------------- // - ImFontAtlasAddDrawListSharedData() // - ImFontAtlasRemoveDrawListSharedData() @@ -3551,6 +3551,22 @@ static void ImFontAtlasBuildUpdateLinesTexData(ImFontAtlas* atlas, bool add_and_ //----------------------------------------------------------------------------------------------------------------------------- +void ImFontAtlasBuildReloadAll(ImFontAtlas* atlas) +{ + const ImFontLoader* main_loader = atlas->FontLoader; + ImFontAtlasBuildSetupFontLoader(atlas, NULL); + ImFontAtlasBuildSetupFontLoader(atlas, main_loader); +} + +void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFontConfig* src) +{ + // FIXME-NEWATLAS: rebuild single font not supported yet. + IM_UNUSED(src); + ImFontAtlasBuildReloadAll(atlas); +} + +//----------------------------------------------------------------------------------------------------------------------------- + bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src) { ImFont* font = src->DstFont; @@ -3794,7 +3810,7 @@ void ImFontAtlasBuildDiscardFontBaked(ImFontAtlas* atlas, ImFont* font, ImFontBa font->LastBaked = NULL; } -void ImFontAtlasBuildDiscardFont(ImFontAtlas* atlas, ImFont* font) +void ImFontAtlasBuildDiscardFontBakes(ImFontAtlas* atlas, ImFont* font) { if (ImFontAtlasBuilder* builder = atlas->Builder) // This can be called from font destructor for (int baked_n = 0; baked_n < builder->BakedPool.Size; baked_n++) @@ -4943,7 +4959,7 @@ ImFont::~ImFont() void ImFont::ClearOutputData() { if (ImFontAtlas* atlas = ContainerAtlas) - ImFontAtlasBuildDiscardFont(atlas, this); + ImFontAtlasBuildDiscardFontBakes(atlas, this); FallbackChar = EllipsisChar = 0; memset(Used8kPagesMap, 0, sizeof(Used8kPagesMap)); LastBaked = NULL; diff --git a/imgui_internal.h b/imgui_internal.h index c1857aafb..c92aea666 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3775,10 +3775,13 @@ IMGUI_API void ImFontAtlasBuildGrowTexture(ImFontAtlas* atlas, int IMGUI_API void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas); IMGUI_API ImVec2i ImFontAtlasBuildGetTextureSizeEstimate(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasBuildReloadAll(ImFontAtlas* atlas); // Reinit/rebuild, notably if font loader params have changed. +IMGUI_API void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFontConfig* src); // Reinit/rebuild, notably if font loader params have changed. + IMGUI_API bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src); IMGUI_API void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src); IMGUI_API void ImFontAtlasBuildDiscardBakes(ImFontAtlas* atlas, int unused_frames); -IMGUI_API void ImFontAtlasBuildDiscardFont(ImFontAtlas* atlas, ImFont* font); +IMGUI_API void ImFontAtlasBuildDiscardFontBakes(ImFontAtlas* atlas, ImFont* font); IMGUI_API void ImFontAtlasBuildDiscardFontSource(ImFontAtlas* atlas, ImFontConfig* src); IMGUI_API ImFontBaked* ImFontAtlasBuildAddFontBaked(ImFontAtlas* atlas, ImFont* font, float font_size, ImGuiID baked_id); IMGUI_API ImFontBaked* ImFontAtlasBuildGetClosestFontBakedMatch(ImFontAtlas* atlas, ImFont* font, float font_size); diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index fd6920e0c..edd6bdd14 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -578,7 +578,7 @@ bool ImGui_ImplFreetype_FontSrcContainsGlyph(ImFontAtlas* atlas, ImFontConfig* s const ImFontLoader* ImGuiFreeType::GetFontLoader() { static ImFontLoader loader; - loader.Name = "freetype"; + loader.Name = "FreeType"; loader.LoaderInit = ImGui_ImplFreeType_LoaderInit; loader.LoaderShutdown = ImGui_ImplFreeType_LoaderShutdown; loader.FontSrcInit = ImGui_ImplFreeType_FontSrcInit; @@ -598,6 +598,22 @@ void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* u GImGuiFreeTypeAllocatorUserData = user_data; } +bool ImGuiFreeType::DebugEditFontBuilderFlags(unsigned int* p_font_loader_flags) +{ + bool edited = false; + edited |= ImGui::CheckboxFlags("NoHinting", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_NoHinting); + edited |= ImGui::CheckboxFlags("NoAutoHint", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_NoAutoHint); + edited |= ImGui::CheckboxFlags("ForceAutoHint",p_font_loader_flags, ImGuiFreeTypeBuilderFlags_ForceAutoHint); + edited |= ImGui::CheckboxFlags("LightHinting", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_LightHinting); + edited |= ImGui::CheckboxFlags("MonoHinting", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_MonoHinting); + edited |= ImGui::CheckboxFlags("Bold", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_Bold); + edited |= ImGui::CheckboxFlags("Oblique", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_Oblique); + edited |= ImGui::CheckboxFlags("Monochrome", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_Monochrome); + edited |= ImGui::CheckboxFlags("LoadColor", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_LoadColor); + edited |= ImGui::CheckboxFlags("Bitmap", p_font_loader_flags, ImGuiFreeTypeBuilderFlags_Bitmap); + return edited; +} + #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG // For more details, see https://gitlab.freedesktop.org/freetype/freetype-demos/-/blob/master/src/rsvg-port.c // The original code from the demo is licensed under CeCILL-C Free Software License Agreement (https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/LICENSE.TXT) diff --git a/misc/freetype/imgui_freetype.h b/misc/freetype/imgui_freetype.h index 2d7b3a34f..b4e9ba1fd 100644 --- a/misc/freetype/imgui_freetype.h +++ b/misc/freetype/imgui_freetype.h @@ -49,6 +49,9 @@ namespace ImGuiFreeType // However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired. IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr); + // Display UI to edit FontBuilderFlags in ImFontAtlas (shared) or ImFontConfig (single source) + IMGUI_API bool DebugEditFontBuilderFlags(unsigned int* p_font_loader_flags); + // Obsolete names (will be removed soon) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS //static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE'