Browse Source

Fonts: GetFontBaked() default to searching for closest size font.

ocornut 6 months ago
parent
commit
161e222322
2 changed files with 43 additions and 11 deletions
  1. 42 11
      imgui_draw.cpp
  2. 1 0
      imgui_internal.h

+ 42 - 11
imgui_draw.cpp

@@ -3716,6 +3716,30 @@ ImFontBaked* ImFontAtlasBuildAddFontBaked(ImFontAtlas* atlas, ImFont* font, floa
     return baked;
 }
 
+// FIXME-OPT: This is not a fast query. Adding a BakedCount field in Font might allow to take a shortcut for the most common case.
+ImFontBaked* ImFontAtlasBuildGetClosestFontBakedMatch(ImFontAtlas* atlas, ImFont* font, float font_size)
+{
+    ImFontAtlasBuilder* builder = atlas->Builder;
+    ImFontBaked* closest_larger_match = NULL;
+    ImFontBaked* closest_smaller_match = NULL;
+    for (int baked_n = 0; baked_n < builder->BakedPool.Size; baked_n++)
+    {
+        ImFontBaked* baked = &builder->BakedPool[baked_n];
+        if (baked->ContainerFont != font || baked->WantDestroy)
+            continue;
+        if (baked->Size > font_size && (closest_larger_match == NULL || baked->Size < closest_larger_match->Size))
+            closest_larger_match = baked;
+        if (baked->Size < font_size && (closest_smaller_match == NULL || baked->Size > closest_smaller_match->Size))
+            closest_smaller_match = baked;
+    }
+    if (closest_larger_match)
+        if (closest_smaller_match == NULL || (closest_larger_match->Size >= font_size * 2.0f && closest_smaller_match->Size > font_size * 0.5f))
+            return closest_larger_match;
+    if (closest_smaller_match)
+        return closest_smaller_match;
+    return NULL;
+}
+
 void ImFontAtlasBuildDiscardFontBaked(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked)
 {
     ImFontAtlasBuilder* builder = atlas->Builder;
@@ -4976,9 +5000,9 @@ void ImFontAtlasBakedSetFontGlyphBitmap(ImFontAtlas* atlas, ImFontBaked* baked,
     ImFontAtlasTextureBlockQueueUpload(atlas, tex, r->x, r->y, r->w, r->h);
 }
 
+// FIXME-NEWATLAS: Implement AddRemapChar() which was removed since transitioning to baked logic.
 void ImFont::AddRemapChar(ImWchar from_codepoint, ImWchar to_codepoint, bool overwrite_dst)
 {
-    // FIXME-BAKED: Implement AddRemapChar()
     IM_UNUSED(from_codepoint);
     IM_UNUSED(to_codepoint);
     IM_UNUSED(overwrite_dst);
@@ -5092,8 +5116,8 @@ ImFontBaked* ImFont::GetFontBaked(float size)
     ImFontAtlas* atlas = ContainerAtlas;
     ImFontAtlasBuilder* builder = atlas->Builder;
 
-    // FIXME-BAKED: Design for picking a nearest size?
-    // FIXME-BAKED: Altering font density won't work right away.
+    // FIXME-NEWATLAS: Design for picking a nearest size based on some criterias?
+    // FIXME-NEWATLAS: Altering font density won't work right away.
     ImGuiID baked_id = ImFontAtlasBakedGetId(FontId, size);
     ImFontBaked** p_baked_in_map = (ImFontBaked**)builder->BakedMap.GetVoidPtrRef(baked_id);
     baked = *p_baked_in_map;
@@ -5105,17 +5129,24 @@ ImFontBaked* ImFont::GetFontBaked(float size)
         return baked;
     }
 
-    // FIXME-BAKED: If loading is locked, find closest match
-    if (Flags & ImFontFlags_LockBakedSizes)
+    // If atlas is locked, find closest match
+    // FIXME-OPT: This is not an optimal query.
+    if ((Flags & ImFontFlags_LockBakedSizes) || atlas->Locked)
     {
-        IM_ASSERT(LastBaked);
-        return LastBaked;
+        baked = ImFontAtlasBuildGetClosestFontBakedMatch(atlas, this, size);
+        if (baked != NULL)
+        {
+            baked->LastUsedFrame = builder->FrameCount;
+            LastBaked = baked;
+            return baked;;
+        }
+        if (atlas->Locked)
+        {
+            IM_ASSERT(!atlas->Locked && "Cannot use dynamic font size with a locked ImFontAtlas!"); // Locked because rendering backend does not support ImGuiBackendFlags_RendererHasTextures!
+            return NULL;
+        }
     }
 
-    // FIXME-BAKED: If atlas is locked, find closest match
-    if (atlas->Locked)
-        IM_ASSERT(!atlas->Locked && "Cannot use dynamic font size with a locked ImFontAtlas!"); // Locked because rendering backend does not support ImGuiBackendFlags_RendererHasTextures!
-
     // Create new
     baked = ImFontAtlasBuildAddFontBaked(atlas, this, size, baked_id);
     LastBaked = baked;

+ 1 - 0
imgui_internal.h

@@ -3779,6 +3779,7 @@ IMGUI_API void              ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas*
 IMGUI_API void              ImFontAtlasBuildDiscardBakes(ImFontAtlas* atlas, int unused_frames);
 IMGUI_API void              ImFontAtlasBuildDiscardFont(ImFontAtlas* atlas, ImFont* font);
 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);
 IMGUI_API void              ImFontAtlasBuildDiscardFontBaked(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked);
 IMGUI_API void              ImFontAtlasBuildDiscardFontBakedGlyph(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked, ImFontGlyph* glyph);
 IMGUI_API void              ImFontAtlasBuildPreloadAllGlyphRanges(ImFontAtlas* atlas); // Legacy