Преглед на файлове

Fonts: Fallback glyph is now lazily loaded on demand (yay!). Moving ImFontBaked:: functions outside of class.

ocornut преди 6 месеца
родител
ревизия
d8a612f73b
променени са 2 файла, в които са добавени 48 реда и са изтрити 36 реда
  1. 2 3
      imgui.h
  2. 46 33
      imgui_draw.cpp

+ 2 - 3
imgui.h

@@ -3652,7 +3652,8 @@ struct ImFontBaked
     // [Internal] Members: Cold
     float                       Ascent, Descent;    // 4+4   // out // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled)
     unsigned int                MetricsTotalSurface:26;// 3  // out // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)
-    unsigned int                WantDestroy:1;      // 1     //     // Queued for destroy
+    unsigned int                WantDestroy:1;         // 0  //     // Queued for destroy
+    unsigned int                LockLoadingFallback:1; // 0  //     //
     int                         LastUsedFrame;      // 4     //     // Record of that time this was bounds
     ImGuiID                     BakedId;            // 4     //
     ImFont*                     ContainerFont;      // 4-8   // in  // Parent font
@@ -3665,8 +3666,6 @@ struct ImFontBaked
     IMGUI_API ImFontGlyph*      FindGlyphNoFallback(ImWchar c);     // Return NULL if glyph doesn't exist
     IMGUI_API float             GetCharAdvance(ImWchar c);
     IMGUI_API bool              IsGlyphLoaded(ImWchar c);
-    IMGUI_API ImFontGlyph*      BuildLoadGlyph(ImWchar c);
-    IMGUI_API void              BuildGrowIndex(int new_size);
 };
 
 // Font flags

+ 46 - 33
imgui_draw.cpp

@@ -2499,6 +2499,7 @@ void ImTextureData::DestroyPixels()
 // - ImFontAtlasBuildAddFont()
 // - ImFontAtlasBuildSetupFontBakedEllipsis()
 // - ImFontAtlasBuildSetupFontBakedBlanks()
+// - ImFontAtlasBuildSetupFontBakedFallback()
 // - ImFontAtlasBuildSetupFontSpecialGlyphs()
 // - ImFontAtlasBuildDiscardBakes()
 // - ImFontAtlasBuildDiscardFontBakedGlyph()
@@ -2527,7 +2528,8 @@ void ImTextureData::DestroyPixels()
 // - ImFontAtlasPackAddRect()
 // - ImFontAtlasPackGetRect()
 //-----------------------------------------------------------------------------
-// - ImFont::BuildLoadGlyph()
+// - ImFontBaked_BuildGrowIndex()
+// - ImFontBaked_BuildLoadGlyph()
 // - ImFontAtlasDebugLogTextureRequests()
 //-----------------------------------------------------------------------------
 // - ImFontAtlasGetFontLoaderForStbTruetype()
@@ -3242,7 +3244,7 @@ int ImFontAtlas::AddCustomRectFontGlyphForSize(ImFont* font, float font_size, Im
         ImFontAtlasTextureBlockQueueUpload(this, TexData, r->x, r->y, r->w, r->h);
 
     if (baked->IsGlyphLoaded(codepoint))
-        ImFontAtlasBuildDiscardFontBakedGlyph(this, font, baked, (ImFontGlyph*)(void*)baked->FindGlyph(codepoint));
+        ImFontAtlasBuildDiscardFontBakedGlyph(this, font, baked, baked->FindGlyph(codepoint));
 
     ImFontGlyph glyph;
     glyph.Codepoint = codepoint;
@@ -3367,7 +3369,7 @@ void ImFontAtlasBuildPreloadAllGlyphRanges(ImFontAtlas* atlas)
             IM_ASSERT(ranges != NULL);
             for (; ranges[0]; ranges += 2)
                 for (unsigned int c = ranges[0]; c <= ranges[1] && c <= IM_UNICODE_CODEPOINT_MAX; c++) //-V560
-                    baked->FindGlyphNoFallback((ImWchar)c);
+                    baked->FindGlyph((ImWchar)c);
         }
 }
 
@@ -3587,25 +3589,23 @@ static ImFontGlyph* ImFontAtlasBuildSetupFontBakedEllipsis(ImFontAtlas* atlas, I
     return glyph;
 }
 
-static void ImFontAtlasBuildSetupFontBakedSpecialGlyphs(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked)
+// Load fallback in order to obtain its index
+// (this is called from in hot-path so we avoid extraneous parameters to minimize impact on code size)
+static void ImFontAtlasBuildSetupFontBakedFallback(ImFontBaked* baked)
 {
-    // Mark space as always hidden (not strictly correct/necessary. but some e.g. icons fonts don't have a space. it tends to look neater in previews)
-    ImFontGlyph* space_glyph = (ImFontGlyph*)(void*)baked->FindGlyphNoFallback((ImWchar)' ');
-    if (space_glyph != NULL)
-        space_glyph->Visible = false;
-
-    // Load fallback in order to obtain its index
-    // FIXME-NEWATLAS: could we use a scheme where this is lazily loaded?
     IM_ASSERT(baked->FallbackGlyphIndex == -1);
+    IM_ASSERT(baked->FallbackAdvanceX == 0.0f);
+    ImFont* font = baked->ContainerFont;
     ImFontGlyph* fallback_glyph = NULL;
     if (font->FallbackChar != 0)
         fallback_glyph = baked->FindGlyphNoFallback(font->FallbackChar);
     if (fallback_glyph == NULL)
     {
+        ImFontGlyph* space_glyph = baked->FindGlyphNoFallback((ImWchar)' ');
         ImFontGlyph glyph;
         glyph.Codepoint = 0;
         glyph.AdvanceX = space_glyph ? space_glyph->AdvanceX : IM_ROUND(baked->Size * 0.40f);
-        fallback_glyph = ImFontAtlasBakedAddFontGlyph(atlas, baked, NULL, &glyph);
+        fallback_glyph = ImFontAtlasBakedAddFontGlyph(font->ContainerAtlas, baked, NULL, &glyph);
     }
     baked->FallbackGlyphIndex = baked->Glyphs.index_from_ptr(fallback_glyph); // Storing index avoid need to update pointer on growth and simplify inner loop code
     baked->FallbackAdvanceX = fallback_glyph->AdvanceX;
@@ -3711,7 +3711,7 @@ ImFontBaked* ImFontAtlasBuildAddFontBaked(ImFontAtlas* atlas, ImFont* font, floa
         loader_data_p += loader->FontBakedSrcLoaderDataSize;
     }
 
-    ImFontAtlasBuildSetupFontBakedSpecialGlyphs(atlas, baked->ContainerFont, baked);
+    ImFontAtlasBuildSetupFontBakedBlanks(atlas, baked);
     return baked;
 }
 
@@ -4260,13 +4260,26 @@ static bool ImFontAtlasBuildAcceptCodepointForSource(ImFontConfig* src, ImWchar
     return true;
 }
 
-ImFontGlyph* ImFontBaked::BuildLoadGlyph(ImWchar codepoint)
+static void ImFontBaked_BuildGrowIndex(ImFontBaked* baked, int new_size)
 {
-    ImFont* font = ContainerFont;
-    ImFontBaked* baked = this;
+    IM_ASSERT(baked->IndexAdvanceX.Size == baked->IndexLookup.Size);
+    if (new_size <= baked->IndexLookup.Size)
+        return;
+    baked->IndexAdvanceX.resize(new_size, -1.0f);
+    baked->IndexLookup.resize(new_size, IM_FONTGLYPH_INDEX_UNUSED);
+}
+
+static ImFontGlyph* ImFontBaked_BuildLoadGlyph(ImFontBaked* baked, ImWchar codepoint)
+{
+    ImFont* font = baked->ContainerFont;
     ImFontAtlas* atlas = font->ContainerAtlas;
     if (atlas->Locked || (font->Flags & ImFontFlags_NoLoadGlyphs))
+    {
+        // Lazily load fallback glyph
+        if (baked->FallbackGlyphIndex == -1 && baked->LockLoadingFallback == 0)
+            ImFontAtlasBuildSetupFontBakedFallback(baked);
         return NULL;
+    }
 
     //char utf8_buf[5];
     //IMGUI_DEBUG_LOG("[font] BuildLoadGlyph U+%04X (%s)\n", (unsigned int)codepoint, ImTextCharToUtf8(utf8_buf, (unsigned int)codepoint));
@@ -4293,8 +4306,14 @@ ImFontGlyph* ImFontBaked::BuildLoadGlyph(ImWchar codepoint)
         loader_user_data_p += loader->FontBakedSrcLoaderDataSize;
     }
 
+    // Lazily load fallback glyph
+    if (baked->LockLoadingFallback)
+        return NULL;
+    if (baked->FallbackGlyphIndex == -1)
+        ImFontAtlasBuildSetupFontBakedFallback(baked);
+
     // Mark index as not found, so we don't attempt the search twice
-    baked->BuildGrowIndex(codepoint + 1);
+    ImFontBaked_BuildGrowIndex(baked, codepoint + 1);
     baked->IndexAdvanceX[codepoint] = baked->FallbackAdvanceX;
     baked->IndexLookup[codepoint] = IM_FONTGLYPH_INDEX_NOT_FOUND;
     return NULL;
@@ -4302,10 +4321,10 @@ ImFontGlyph* ImFontBaked::BuildLoadGlyph(ImWchar codepoint)
 
 // The point of this indirection is to not be inlined in debug mode in order to not bloat inner loop.b
 IM_MSVC_RUNTIME_CHECKS_OFF
-static float BuildLoadGlyphGetAdvanceOrFallback(ImFontBaked* font, unsigned int codepoint)
+static float BuildLoadGlyphGetAdvanceOrFallback(ImFontBaked* baked, unsigned int codepoint)
 {
-    ImFontGlyph* glyph = font->BuildLoadGlyph((ImWchar)codepoint);
-    return glyph ? glyph->AdvanceX : font->FallbackAdvanceX;
+    ImFontGlyph* glyph = ImFontBaked_BuildLoadGlyph(baked, (ImWchar)codepoint);
+    return glyph ? glyph->AdvanceX : baked->FallbackAdvanceX;
 }
 IM_MSVC_RUNTIME_CHECKS_RESTORE
 
@@ -4861,15 +4880,6 @@ void ImFontBaked::ClearOutputData()
     MetricsTotalSurface = 0;
 }
 
-void ImFontBaked::BuildGrowIndex(int new_size)
-{
-    IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size);
-    if (new_size <= IndexLookup.Size)
-        return;
-    IndexAdvanceX.resize(new_size, -1.0f);
-    IndexLookup.resize(new_size, IM_FONTGLYPH_INDEX_UNUSED);
-}
-
 ImFont::ImFont()
 {
     memset(this, 0, sizeof(*this));
@@ -4950,7 +4960,7 @@ ImFontGlyph* ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked
 
     // Update lookup tables
     int codepoint = glyph.Codepoint;
-    baked->BuildGrowIndex(codepoint + 1);
+    ImFontBaked_BuildGrowIndex(baked, codepoint + 1);
     baked->IndexAdvanceX[codepoint] = glyph.AdvanceX;
     baked->IndexLookup[codepoint] = (ImU16)glyph_idx;
     const int page_n = codepoint / 8192;
@@ -5002,7 +5012,7 @@ ImFontGlyph* ImFontBaked::FindGlyph(ImWchar c)
         if (i != IM_FONTGLYPH_INDEX_UNUSED)
             return &Glyphs.Data[i];
     }
-    ImFontGlyph* glyph = BuildLoadGlyph(c);
+    ImFontGlyph* glyph = ImFontBaked_BuildLoadGlyph(this, c);
     return glyph ? glyph : &Glyphs.Data[FallbackGlyphIndex];
 }
 
@@ -5017,7 +5027,10 @@ ImFontGlyph* ImFontBaked::FindGlyphNoFallback(ImWchar c)
         if (i != IM_FONTGLYPH_INDEX_UNUSED)
             return &Glyphs.Data[i];
     }
-    return BuildLoadGlyph(c);
+    LockLoadingFallback = true; // This is actually a rare call, not done in hot-loop, so we prioritize not adding extra cruft to ImFontBaked_BuildLoadGlyph() call sites.
+    ImFontGlyph* glyph = ImFontBaked_BuildLoadGlyph(this, c);
+    LockLoadingFallback = false;
+    return glyph;
 }
 
 bool ImFontBaked::IsGlyphLoaded(ImWchar c)
@@ -5060,7 +5073,7 @@ float ImFontBaked::GetCharAdvance(ImWchar c)
     }
 
     // Same as BuildLoadGlyphGetAdvanceOrFallback():
-    const ImFontGlyph* glyph = BuildLoadGlyph(c);
+    const ImFontGlyph* glyph = ImFontBaked_BuildLoadGlyph(this, c);
     return glyph ? glyph->AdvanceX : FallbackAdvanceX;
 }
 IM_MSVC_RUNTIME_CHECKS_RESTORE