diff --git a/imgui.cpp b/imgui.cpp index 974c9a56b..a4fc5ecce 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -21204,7 +21204,7 @@ static void MetricsHelpMarker(const char* desc) } #ifdef IMGUI_ENABLE_FREETYPE -namespace ImGuiFreeType { IMGUI_API const ImFontLoader* GetBackendIOForFreeType(); } +namespace ImGuiFreeType { IMGUI_API const ImFontLoader* GetFontLoader(); } #endif // [DEBUG] List fonts in a font atlas and display its texture @@ -21227,7 +21227,7 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas) #endif SameLine(); #ifdef IMGUI_ENABLE_FREETYPE - const ImFontLoader* loader_freetype = ImGuiFreeType::GetBackendIOForFreeType(); + const ImFontLoader* loader_freetype = ImGuiFreeType::GetFontLoader(); if (RadioButton("FreeType", loader_current == loader_freetype)) ImFontAtlasBuildSetupFontLoader(atlas, loader_freetype); #else diff --git a/imgui.h b/imgui.h index 5f26ebf7a..a10cc1011 100644 --- a/imgui.h +++ b/imgui.h @@ -3723,8 +3723,6 @@ struct ImFontAtlas void* FontLoaderData; // Font backend opaque storage unsigned int FontBuilderFlags; // [FIXME: Should be called FontLoaderFlags] Shared flags (for all fonts) for font loader. THIS IS BUILD IMPLEMENTATION DEPENDENT (e.g. . Per-font override is also available in ImFontConfig. int RefCount; // Number of contexts using this atlas - int _PackedSurface; // Number of packed pixels. Used when compacting to heuristically find the ideal texture size. - int _PackedRects; // Number of packed rectangles. // [Obsolete] //int TexDesiredWidth; // OBSOLETED in 1.91.5 (force texture width before calling Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ecc633b4b..c4405aba6 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2506,6 +2506,7 @@ void ImTextureData::DestroyPixels() //----------------------------------------------------------------------------- // - ImFontAtlasBuildSetTexture() // - ImFontAtlasBuildAddTexture() +// - ImFontAtlasBuildMakeSpace() // - ImFontAtlasBuildRepackTexture() // - ImFontAtlasBuildGrowTexture() // - ImFontAtlasBuildCompactTexture() @@ -3524,7 +3525,7 @@ bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src) // Rasterize our own ellipsis character from a dot. // This may seem overly complicated right now but the point is to exercise and improve a technique which should be increasingly used. -// FIXME-NEWATLAS: This borrows too much from FontBackend_FontAddGlyph() and suggest that we should add further helpers. +// FIXME-NEWATLAS: This borrows too much from FontLoader's FontAddGlyph() and suggest that we should add further helpers. static void ImFontAtlasBuildSetupFontCreateEllipsisFromDot(ImFontAtlas* atlas, ImFontConfig* src, const ImFontGlyph* dot_glyph) { ImFont* font = src->DstFont; @@ -3826,7 +3827,7 @@ void ImFontAtlasBuildGrowTexture(ImFontAtlas* atlas, int old_tex_w, int old_tex_ IM_ASSERT(ImIsPowerOfTwo(atlas->TexMinWidth) && ImIsPowerOfTwo(atlas->TexMaxWidth) && ImIsPowerOfTwo(atlas->TexMinHeight) && ImIsPowerOfTwo(atlas->TexMaxHeight)); // Grow texture so it follows roughly a square. - // FIXME-NEWATLAS-V1: Take account of RectsDiscardedSurface: may not need to grow. + // Caller should be taking account of RectsDiscardedSurface and may not need to grow. int new_tex_w = (old_tex_h < old_tex_w) ? old_tex_w : old_tex_w * 2; int new_tex_h = (old_tex_h < old_tex_w) ? old_tex_h * 2 : old_tex_h; @@ -3842,6 +3843,16 @@ void ImFontAtlasBuildGrowTexture(ImFontAtlas* atlas, int old_tex_w, int old_tex_ ImFontAtlasBuildRepackTexture(atlas, new_tex_w, new_tex_h); } +void ImFontAtlasBuildMakeSpace(ImFontAtlas* atlas) +{ + // Currently using a heuristic for repack without growing. + ImFontAtlasBuilder* builder = atlas->Builder; + if (builder->RectsDiscardedSurface < builder->RectsPackedSurface * 0.20f) + ImFontAtlasBuildGrowTexture(atlas); + else + ImFontAtlasBuildRepackTexture(atlas, atlas->TexData->Width, atlas->TexData->Height); +} + ImVec2i ImFontAtlasBuildGetTextureSizeEstimate(ImFontAtlas* atlas) { int min_w = ImUpperPowerOfTwo(atlas->TexMinWidth); @@ -3852,7 +3863,7 @@ ImVec2i ImFontAtlasBuildGetTextureSizeEstimate(ImFontAtlas* atlas) ImFontAtlasBuilder* builder = atlas->Builder; min_w = ImMax(ImUpperPowerOfTwo(builder->MaxRectSize.x), min_w); min_h = ImMax(ImUpperPowerOfTwo(builder->MaxRectSize.y), min_h); - const int surface_approx = atlas->_PackedSurface - builder->RectsDiscardedSurface; // Expected surface after repack + const int surface_approx = builder->RectsPackedSurface - builder->RectsDiscardedSurface; // Expected surface after repack const int surface_sqrt = (int)sqrtf((float)surface_approx); int new_tex_w; @@ -3896,10 +3907,10 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas) ImFontAtlasBuilder* builder = atlas->Builder; // Select Backend - // - Note that we do not reassign to atlas->FontBackendIO, since it is likely to point to static data which + // - Note that we do not reassign to atlas->FontLoader, since it is likely to point to static data which // may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are - // using a hot-reloading scheme that messes up static data, store your own instance of ImFontBackendIO somewhere - // and point to it instead of pointing directly to return value of the GetBackendIOXXX functions. + // using a hot-reloading scheme that messes up static data, store your own instance of FontLoader somewhere + // and point to it instead of pointing directly to return value of the GetFontLoaderXXX functions. if (atlas->FontLoader == NULL) { #ifdef IMGUI_ENABLE_FREETYPE @@ -3961,7 +3972,7 @@ void ImFontAtlasPackInit(ImFontAtlas * atlas) builder->PackNodes.resize(pack_node_count); IM_STATIC_ASSERT(sizeof(stbrp_context) <= sizeof(stbrp_context_opaque)); stbrp_init_target((stbrp_context*)(void*)&builder->PackContext, tex->Width, tex->Height, builder->PackNodes.Data, builder->PackNodes.Size); - atlas->_PackedSurface = atlas->_PackedRects = 0; + builder->RectsPackedSurface = builder->RectsPackedCount = 0; builder->MaxRectSize = ImVec2i(0, 0); builder->MaxRectBounds = ImVec2i(0, 0); } @@ -4044,14 +4055,14 @@ ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h, ImFon return -1; } - // Resize atlas! (this should be a rare event) - ImFontAtlasBuildGrowTexture(atlas); + // Resize or repack atlas! (this should be a rare event) + ImFontAtlasBuildMakeSpace(atlas); } builder->MaxRectBounds.x = ImMax(builder->MaxRectBounds.x, r.x + r.w + pack_padding); builder->MaxRectBounds.y = ImMax(builder->MaxRectBounds.y, r.y + r.h + pack_padding); - atlas->_PackedSurface += (w + pack_padding) * (h + pack_padding); - atlas->_PackedRects++; + builder->RectsPackedCount++; + builder->RectsPackedSurface += (w + pack_padding) * (h + pack_padding); builder->Rects.push_back(r); if (overwrite_entry != NULL) diff --git a/imgui_internal.h b/imgui_internal.h index 07dd7a1e1..27f245d42 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3971,6 +3971,8 @@ struct ImFontAtlasBuilder ImVector RectsIndex; // ImFontAtlasRectId -> index into Rects[] ImVector TempBuffer; // Misc scratch buffer int RectsIndexFreeListStart;// First unused entry + int RectsPackedCount; // Number of packed rectangles. + int RectsPackedSurface; // Number of packed pixels. Used when compacting to heuristically find the ideal texture size. int RectsDiscardedCount; int RectsDiscardedSurface; ImVec2i MaxRectSize; // Largest rectangle to pack (de-facto used as a "minimum texture size") @@ -3995,6 +3997,7 @@ IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildDestroy(ImFontAtlas* atlas); IMGUI_API ImTextureData* ImFontAtlasBuildAddTexture(ImFontAtlas* atlas, int w, int h); +IMGUI_API void ImFontAtlasBuildMakeSpace(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildRepackTexture(ImFontAtlas* atlas, int w, int h); IMGUI_API void ImFontAtlasBuildGrowTexture(ImFontAtlas* atlas, int old_w = -1, int old_h = -1); IMGUI_API void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas);