Browse Source

Fonts: Basic heuristic to repack instead of growing. Moved rects count/surface to internals.

ocornut 7 months ago
parent
commit
8ed4e2dde7
4 changed files with 27 additions and 15 deletions
  1. 2 2
      imgui.cpp
  2. 0 2
      imgui.h
  3. 22 11
      imgui_draw.cpp
  4. 3 0
      imgui_internal.h

+ 2 - 2
imgui.cpp

@@ -15594,7 +15594,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
@@ -15628,7 +15628,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

+ 0 - 2
imgui.h

@@ -3626,8 +3626,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)

+ 22 - 11
imgui_draw.cpp

@@ -2504,6 +2504,7 @@ void ImTextureData::DestroyPixels()
 //-----------------------------------------------------------------------------
 // - ImFontAtlasBuildSetTexture()
 // - ImFontAtlasBuildAddTexture()
+// - ImFontAtlasBuildMakeSpace()
 // - ImFontAtlasBuildRepackTexture()
 // - ImFontAtlasBuildGrowTexture()
 // - ImFontAtlasBuildCompactTexture()
@@ -3521,7 +3522,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;
@@ -3823,7 +3824,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;
 
@@ -3839,6 +3840,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);
@@ -3849,7 +3860,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;
@@ -3893,10 +3904,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
@@ -3958,7 +3969,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);
 }
@@ -4041,14 +4052,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)

+ 3 - 0
imgui_internal.h

@@ -3685,6 +3685,8 @@ struct ImFontAtlasBuilder
     ImVector<ImFontAtlasRectEntry> RectsIndex;          // ImFontAtlasRectId -> index into Rects[]
     ImVector<unsigned char>     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")
@@ -3709,6 +3711,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);