Browse Source

Fonts: Core allocates per-baked-per-src backend buffers, to allow having custom backend per font source. Backend BakedInit/Destroy/AddGlyph process a single source.

ocornut 6 months ago
parent
commit
1cfc0de31d
4 changed files with 134 additions and 129 deletions
  1. 1 1
      imgui.h
  2. 74 55
      imgui_draw.cpp
  3. 8 4
      imgui_internal.h
  4. 51 69
      misc/freetype/imgui_freetype.cpp

+ 1 - 1
imgui.h

@@ -3654,7 +3654,7 @@ struct ImFontBaked
     int                         LastUsedFrame;      // 4     //     // Record of that time this was bounds
     ImGuiID                     BakedId;            // 4     //
     ImFont*                     ContainerFont;      // 4-8   // in  // Parent font
-    void*                       FontBackendData;    // 4-8   //     // Font backend opaque storage (per baked font)
+    void*                       FontLoaderDatas;    // 4-8   //     // Font loader opaque storage (per baked font * sources): single contiguous buffer allocated by imgui, passed to loader.
 
     // Functions
     IMGUI_API ImFontBaked();

+ 74 - 55
imgui_draw.cpp

@@ -3531,7 +3531,7 @@ bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src)
 
 // Create a compact, baked "..." if it doesn't exist, by using the ".".
 // 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 FontLoader's FontLoaderGlyph() handlers and suggest that we should add further helpers.
+// FIXME-NEWATLAS: This borrows too much from FontLoader's FontLoadGlyph() handlers and suggest that we should add further helpers.
 static ImFontGlyph* ImFontAtlasBuildSetupFontBakedEllipsis(ImFontAtlas* atlas, ImFontBaked* baked)
 {
     ImFont* font = baked->ContainerFont;
@@ -3670,6 +3670,31 @@ void ImFontAtlasBuildDiscardFontBakedGlyph(ImFontAtlas* atlas, ImFont* font, ImF
     baked->IndexAdvanceX[c] = baked->FallbackAdvanceX;
 }
 
+ImFontBaked* ImFontAtlasBuildAddFontBaked(ImFontAtlas* atlas, ImFont* font, float size, ImGuiID baked_id)
+{
+    IMGUI_DEBUG_LOG_FONT("[font] Created baked %.2fpx\n", size);
+    ImFontBaked* baked = atlas->Builder->BakedPool.push_back(ImFontBaked());
+    baked->Size = size;
+    baked->BakedId = baked_id;
+    baked->ContainerFont = font;
+    baked->LastUsedFrame = atlas->Builder->FrameCount;
+
+    // Initialize backend data
+    size_t loader_data_size = font->SourcesCount * atlas->FontLoader->FontBakedSrcLoaderDataSize;
+    baked->FontLoaderDatas = (loader_data_size > 0) ? IM_ALLOC(loader_data_size) : NULL;
+    char* backend_user_data_p = (char*)baked->FontLoaderDatas;
+    for (int src_n = 0; src_n < font->SourcesCount; src_n++)
+    {
+        ImFontConfig* src = &font->Sources[src_n];
+        if (atlas->FontLoader->FontBakedInit)
+            atlas->FontLoader->FontBakedInit(atlas, src, baked, backend_user_data_p);
+        backend_user_data_p += atlas->FontLoader->FontBakedSrcLoaderDataSize;
+    }
+
+    ImFontAtlasBuildSetupFontBakedSpecialGlyphs(atlas, baked->ContainerFont, baked);
+    return baked;
+}
+
 void ImFontAtlasBuildDiscardFontBaked(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked)
 {
     ImFontAtlasBuilder* builder = atlas->Builder;
@@ -3679,9 +3704,19 @@ void ImFontAtlasBuildDiscardFontBaked(ImFontAtlas* atlas, ImFont* font, ImFontBa
         if (glyph.PackId >= 0)
             ImFontAtlasPackDiscardRect(atlas, glyph.PackId);
 
-    if (atlas->FontLoader->FontBakedDestroy)
-        atlas->FontLoader->FontBakedDestroy(atlas, baked);
-
+    char* backend_user_data_p = (char*)baked->FontLoaderDatas;
+    for (int src_n = 0; src_n < font->SourcesCount; src_n++)
+    {
+        ImFontConfig* src = &font->Sources[src_n];
+        if (atlas->FontLoader->FontBakedDestroy)
+            atlas->FontLoader->FontBakedDestroy(atlas, src, baked, backend_user_data_p);
+        backend_user_data_p += atlas->FontLoader->FontBakedSrcLoaderDataSize;
+    }
+    if (baked->FontLoaderDatas)
+    {
+        IM_FREE(baked->FontLoaderDatas);
+        baked->FontLoaderDatas = NULL;
+    }
     builder->BakedMap.SetVoidPtr(baked->BakedId, NULL);
     builder->BakedDiscardedCount++;
     baked->ClearOutputData();
@@ -4017,7 +4052,7 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
 #else
         IM_ASSERT(0); // Invalid Build function
 #endif
-        return; // ImFontAtlasBuildSetupFontBackendIO() automatically call ImFontAtlasBuildInit()
+        return; // ImFontAtlasBuildSetupFontLoader() automatically call ImFontAtlasBuildInit()
     }
 
     // Create initial texture size
@@ -4191,6 +4226,16 @@ ImFontAtlasRect* ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id
     return &builder->Rects[index_entry->TargetIndex];
 }
 
+// Important! This assume by ImFontConfig::GlyphFilter is a SMALL ARRAY (e.g. <10 entries)
+static bool ImFontAtlasBuildAcceptCodepointForSource(ImFontConfig* src, ImWchar codepoint)
+{
+    if (const ImWchar* exclude_list = src->GlyphExcludeRanges)
+        for (; exclude_list[0] != 0; exclude_list += 2)
+            if (codepoint >= exclude_list[0] && codepoint <= exclude_list[1])
+                return false;
+    return true;
+}
+
 ImFontGlyph* ImFontBaked::BuildLoadGlyph(ImWchar codepoint)
 {
     ImFont* font = ContainerFont;
@@ -4214,18 +4259,25 @@ ImFontGlyph* ImFontBaked::BuildLoadGlyph(ImWchar codepoint)
 
     // Call backend
     const ImFontLoader* font_loader = atlas->FontLoader;
-    if (!font_loader->FontBakedAddGlyph(atlas, baked, srcs, srcs_count, codepoint))
+    char* backend_user_data_p = (char*)baked->FontLoaderDatas;
+    for (int src_n = 0; src_n < srcs_count; src_n++)
     {
-        // Mark index as not found, so we don't attempt the search twice
-        baked->BuildGrowIndex(codepoint + 1);
-        baked->IndexAdvanceX[codepoint] = baked->FallbackAdvanceX;
-        baked->IndexLookup[codepoint] = IM_FONTGLYPH_INDEX_NOT_FOUND;
-        return NULL;
+        ImFontConfig* src = &srcs[src_n];
+        if (!src->GlyphExcludeRanges || ImFontAtlasBuildAcceptCodepointForSource(src, codepoint))
+            if (font_loader->FontBakedAddGlyph(atlas, src, baked, backend_user_data_p, codepoint))
+            {
+                // FIXME: Add hooks for e.g. #7962
+                ImFontGlyph* glyph = &baked->Glyphs.back();
+                return glyph;
+            }
+        backend_user_data_p += font_loader->FontBakedSrcLoaderDataSize;
     }
 
-    // FIXME: Add hooks for e.g. #7962
-    ImFontGlyph* glyph = &baked->Glyphs.back();
-    return glyph;
+    // Mark index as not found, so we don't attempt the search twice
+    baked->BuildGrowIndex(codepoint + 1);
+    baked->IndexAdvanceX[codepoint] = baked->FallbackAdvanceX;
+    baked->IndexLookup[codepoint] = IM_FONTGLYPH_INDEX_NOT_FOUND;
+    return NULL;
 }
 
 // The point of this indirection is to not be inlined in debug mode in order to not bloat inner loop.b
@@ -4330,17 +4382,13 @@ static bool ImGui_ImplStbTrueType_FontSrcContainsGlyph(ImFontAtlas* atlas, ImFon
     return glyph_index != 0;
 }
 
-static void ImGui_ImplStbTrueType_FontBakedInit(ImFontAtlas* atlas, ImFontBaked* baked)
+static void ImGui_ImplStbTrueType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void*)
 {
     IM_UNUSED(atlas);
-    ImFont* font = baked->ContainerFont;
 
-    for (int src_n = 0; src_n < font->SourcesCount; src_n++)
+    ImGui_ImplStbTrueType_FontSrcData* bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
+    if (src->MergeMode == false)
     {
-        ImFontConfig* src = &font->Sources[src_n];
-        ImGui_ImplStbTrueType_FontSrcData* bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
-        if (src_n != 0)
-            continue;
         // FIXME-NEWFONTS: reevaluate how to use sizing metrics
         // FIXME-NEWFONTS: make use of line gap value
         float scale_for_layout = bd_font_data->ScaleFactor * baked->Size;
@@ -4351,33 +4399,12 @@ static void ImGui_ImplStbTrueType_FontBakedInit(ImFontAtlas* atlas, ImFontBaked*
     }
 }
 
-// Important! This assume by ImFontConfig::GlyphFilter is a SMALL ARRAY (e.g. <10 entries)
-bool ImFontAtlasBuildAcceptCodepointForSource(ImFontConfig* src, ImWchar codepoint)
-{
-    if (const ImWchar* exclude_list = src->GlyphExcludeRanges)
-        for (; exclude_list[0] != 0; exclude_list += 2)
-            if (codepoint >= exclude_list[0] && codepoint <= exclude_list[1])
-                return false;
-    return true;
-}
-
-static bool ImGui_ImplStbTrueType_FontBakedAddGlyph(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* srcs, int srcs_count, ImWchar codepoint)
+static bool ImGui_ImplStbTrueType_FontBakedAddGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void*, ImWchar codepoint)
 {
     // Search for first font which has the glyph
-    ImGui_ImplStbTrueType_FontSrcData* bd_font_data = NULL;
-    ImFontConfig* src = NULL;
-    int glyph_index = 0;
-    for (int src_n = 0; src_n < srcs_count; src_n++)
-    {
-        src = &srcs[src_n];
-        if (src->GlyphExcludeRanges && !ImFontAtlasBuildAcceptCodepointForSource(src, codepoint))
-            continue;
-        bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
-        IM_ASSERT(bd_font_data);
-        glyph_index = stbtt_FindGlyphIndex(&bd_font_data->FontInfo, (int)codepoint);
-        if (glyph_index != 0)
-            break;
-    }
+    ImGui_ImplStbTrueType_FontSrcData* bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
+    IM_ASSERT(bd_font_data);
+    int glyph_index = stbtt_FindGlyphIndex(&bd_font_data->FontInfo, (int)codepoint);
     if (glyph_index == 0)
         return false; // Not found
 
@@ -5056,17 +5083,9 @@ ImFontBaked* ImFont::GetFontBaked(float size)
         IM_ASSERT(!atlas->Locked && "Cannot use dynamic font size with a locked ImFontAtlas!"); // Locked because rendering backend does not support ImGuiBackendFlags_RendererHasTextures!
 
     // Create new
-    IMGUI_DEBUG_LOG_FONT("[font] Created baked %.2fpx\n", size);
-    baked = builder->BakedPool.push_back(ImFontBaked());
-    baked->Size = size;
-    baked->BakedId = baked_id;
-    baked->ContainerFont = this;
-    baked->LastUsedFrame = ContainerAtlas->Builder->FrameCount;
+    baked = ImFontAtlasBuildAddFontBaked(atlas, this, size, baked_id);
     LastBaked = baked;
     *p_baked_in_map = baked; // To avoid 'builder->BakedMap.SetVoidPtr(baked_id, baked);' while we can.
-    if (atlas->FontLoader->FontBakedInit)
-        atlas->FontLoader->FontBakedInit(atlas, baked);
-    ImFontAtlasBuildSetupFontBakedSpecialGlyphs(atlas, baked->ContainerFont, baked);
 
     return baked;
 }

+ 8 - 4
imgui_internal.h

@@ -3668,9 +3668,13 @@ struct ImFontLoader
     bool            (*FontSrcInit)(ImFontAtlas* atlas, ImFontConfig* src);
     void            (*FontSrcDestroy)(ImFontAtlas* atlas, ImFontConfig* src);
     bool            (*FontSrcContainsGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint);
-    void            (*FontBakedInit)(ImFontAtlas* atlas, ImFontBaked* baked);
-    void            (*FontBakedDestroy)(ImFontAtlas* atlas, ImFontBaked* baked);
-    bool            (*FontBakedAddGlyph)(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* srcs, int srcs_count, ImWchar codepoint);
+    void            (*FontBakedInit)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
+    void            (*FontBakedDestroy)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
+    bool            (*FontBakedAddGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, ImWchar codepoint);
+
+    // Size of backend data, Per Baked * Per Source. Buffers are managed by core to avoid excessive allocations.
+    // FIXME: At this point the two other types of buffers may be managed by core to be consistent?
+    size_t          FontBakedSrcLoaderDataSize;
 
     ImFontLoader()  { memset(this, 0, sizeof(*this)); }
 };
@@ -3770,11 +3774,11 @@ IMGUI_API bool              ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontCo
 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 ImFontBaked*      ImFontAtlasBuildAddFontBaked(ImFontAtlas* atlas, ImFont* font, float font_size, ImGuiID baked_id);
 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
 IMGUI_API void              ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, float size, int* out_oversample_h, int* out_oversample_v);
-IMGUI_API bool              ImFontAtlasBuildAcceptCodepointForSource(ImFontConfig* src, ImWchar codepoint);
 
 IMGUI_API ImFontGlyph*      ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, const ImFontGlyph* in_glyph);
 IMGUI_API void              ImFontAtlasBakedSetFontGlyphBitmap(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, ImFontGlyph* glyph, ImFontAtlasRect* r, const unsigned char* src_pixels, ImTextureFormat src_fmt, int src_pitch);

+ 51 - 69
misc/freetype/imgui_freetype.cpp

@@ -143,7 +143,7 @@ namespace
     //              |                                   |
     //              |------------- advanceX ----------->|
 
-    // Stored in ImFontAtlas::FontLoaderData
+    // Stored in ImFontAtlas::FontLoaderData. ALLOCATED BY US.
     struct ImGui_ImplFreeType_Data
     {
         FT_Library                      Library;
@@ -151,7 +151,7 @@ namespace
         ImGui_ImplFreeType_Data()       { memset((void*)this, 0, sizeof(*this)); }
     };
 
-    // Stored in ImFontBaked::FontBackendData: pointer to SourcesCount instances of this.
+    // Stored in ImFontBaked::FontLoaderDatas: pointer to SourcesCount instances of this. ALLOCATED BY CORE.
     struct ImGui_ImplFreeType_FontSrcBakedData
     {
         FT_Size     FtSize;             // This represent a FT_Face with a given size.
@@ -166,7 +166,7 @@ namespace
         ImGui_ImplFreeType_FontSrcBakedData() { memset((void*)this, 0, sizeof(*this)); }
     };
 
-    // Stored in ImFontConfig::FontLoaderData
+    // Stored in ImFontConfig::FontLoaderData. ALLOCATED BY US.
     struct ImGui_ImplFreeType_FontSrcData
     {
         bool                            InitFont(FT_Library ft_library, ImFontConfig* src, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime.
@@ -437,91 +437,72 @@ void ImGui_ImplFreeType_FontSrcDestroy(ImFontAtlas* atlas, ImFontConfig* src)
     src->FontLoaderData = NULL;
 }
 
-void ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontBaked* baked)
+void ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
 {
     IM_UNUSED(atlas);
-    ImFont* font = baked->ContainerFont;
     const float size = baked->Size;
 
-    IM_ASSERT(baked->FontBackendData == NULL);
-    ImGui_ImplFreeType_FontSrcBakedData* bd_baked_datas = (ImGui_ImplFreeType_FontSrcBakedData*)IM_ALLOC(sizeof(ImGui_ImplFreeType_FontSrcBakedData) * font->SourcesCount);
-    baked->FontBackendData = bd_baked_datas;
-
-    for (int src_n = 0; src_n < font->SourcesCount; src_n++)
+    ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
+    bd_font_data->BakedLastActivated = baked;
+
+    // We use one FT_Size per (source + baked) combination.
+    ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = (ImGui_ImplFreeType_FontSrcBakedData*)loader_data_for_baked_src;
+    IM_ASSERT(bd_baked_data != NULL);
+    IM_PLACEMENT_NEW(bd_baked_data) ImGui_ImplFreeType_FontSrcBakedData();
+
+    FT_New_Size(bd_font_data->FtFace, &bd_baked_data->FtSize);
+    FT_Activate_Size(bd_baked_data->FtSize);
+
+    // Vuhdo 2017: "I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
+    // is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
+    // FT_Set_Pixel_Sizes() doesn't seem to get us the same result."
+    // (FT_Set_Pixel_Sizes() essentially calls FT_Request_Size() with FT_SIZE_REQUEST_TYPE_NOMINAL)
+    FT_Size_RequestRec req;
+    req.type = (bd_font_data->UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
+    req.width = 0;
+    req.height = (uint32_t)(size * 64 * bd_font_data->RasterizationDensity);
+    req.horiResolution = 0;
+    req.vertResolution = 0;
+    FT_Request_Size(bd_font_data->FtFace, &req);
+
+    // Read metrics
+    FT_Size_Metrics metrics = bd_baked_data->FtSize->metrics;
+    bd_baked_data->Ascender = (float)FT_CEIL(metrics.ascender) * bd_font_data->InvRasterizationDensity;
+    bd_baked_data->Descender = (float)FT_CEIL(metrics.descender) * bd_font_data->InvRasterizationDensity;
+    bd_baked_data->LineSpacing = (float)FT_CEIL(metrics.height) * bd_font_data->InvRasterizationDensity;
+    bd_baked_data->LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * bd_font_data->InvRasterizationDensity;
+    bd_baked_data->MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * bd_font_data->InvRasterizationDensity;
+
+    // Output
+    if (src->MergeMode == false)
     {
-        ImFontConfig* src = &font->Sources[src_n];
-        ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontBackendData;
-        bd_font_data->BakedLastActivated = baked;
-
-        // We need one FT_Size per source, so create one ImGui_ImplFreeType_FontBakedData for each source.
-        ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = &bd_baked_datas[src_n];
-        FT_New_Size(bd_font_data->FtFace, &bd_baked_data->FtSize);
-        FT_Activate_Size(bd_baked_data->FtSize);
-
-        // Vuhdo 2017: "I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
-        // is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
-        // FT_Set_Pixel_Sizes() doesn't seem to get us the same result."
-        // (FT_Set_Pixel_Sizes() essentially calls FT_Request_Size() with FT_SIZE_REQUEST_TYPE_NOMINAL)
-        FT_Size_RequestRec req;
-        req.type = (bd_font_data->UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
-        req.width = 0;
-        req.height = (uint32_t)(size * 64 * bd_font_data->RasterizationDensity);
-        req.horiResolution = 0;
-        req.vertResolution = 0;
-        FT_Request_Size(bd_font_data->FtFace, &req);
-
-        // Read metrics
-        FT_Size_Metrics metrics = bd_baked_data->FtSize->metrics;
-        bd_baked_data->Ascender = (float)FT_CEIL(metrics.ascender) * bd_font_data->InvRasterizationDensity;
-        bd_baked_data->Descender = (float)FT_CEIL(metrics.descender) * bd_font_data->InvRasterizationDensity;
-        bd_baked_data->LineSpacing = (float)FT_CEIL(metrics.height) * bd_font_data->InvRasterizationDensity;
-        bd_baked_data->LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * bd_font_data->InvRasterizationDensity;
-        bd_baked_data->MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * bd_font_data->InvRasterizationDensity;
-
-        // Output
-        if (src_n == 0)
-        {
-            baked->Ascent = bd_baked_data->Ascender;
-            baked->Descent = bd_baked_data->Descender;
-        }
+        baked->Ascent = bd_baked_data->Ascender;
+        baked->Descent = bd_baked_data->Descender;
     }
 }
 
-void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas* atlas, ImFontBaked* baked)
+void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
 {
     IM_UNUSED(atlas);
-    ImFont* font = baked->ContainerFont;
-    ImGui_ImplFreeType_FontSrcBakedData* bd_baked_datas = (ImGui_ImplFreeType_FontSrcBakedData*)baked->FontBackendData;
-    for (int src_n = 0; src_n < font->SourcesCount; src_n++)
-        FT_Done_Size(bd_baked_datas[src_n].FtSize);
-    IM_FREE(bd_baked_datas);
-    baked->FontBackendData = NULL;
+    IM_UNUSED(baked);
+    IM_UNUSED(src);
+    ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = (ImGui_ImplFreeType_FontSrcBakedData*)loader_data_for_baked_src;
+    IM_ASSERT(bd_baked_data != NULL);
+    FT_Done_Size(bd_baked_data->FtSize);
+    bd_baked_data->~ImGui_ImplFreeType_FontSrcBakedData(); // ~IM_PLACEMENT_DELETE()
 }
 
-bool ImGui_ImplFreeType_FontBakedAddGlyph(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* srcs, int srcs_count, ImWchar codepoint)
+bool ImGui_ImplFreeType_FontBakedAddGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, ImWchar codepoint)
 {
-    // Search for first font which has the glyph
-    ImGui_ImplFreeType_FontSrcData* bd_font_data = NULL;
-    ImFontConfig* src = NULL;
-    uint32_t glyph_index = 0;
-    for (int src_n = 0; src_n < srcs_count; src_n++)
-    {
-        src = &srcs[src_n];
-        if (src->GlyphExcludeRanges && !ImFontAtlasBuildFilterCodepointForSource(src, codepoint))
-            continue;
-        bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
-        glyph_index = FT_Get_Char_Index(bd_font_data->FtFace, codepoint);
-        if (glyph_index != 0)
-            break;
-    }
+    ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
+    uint32_t glyph_index = FT_Get_Char_Index(bd_font_data->FtFace, codepoint);
     if (glyph_index == 0)
         return false; // Not found
 
     if (bd_font_data->BakedLastActivated != baked)
     {
         // Activate current size
-        int src_n = (int)(font_cfg - srcs);
-        ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = &((ImGui_ImplFreeType_FontSrcBakedData*)baked->FontBackendData)[src_n];
+        ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = (ImGui_ImplFreeType_FontSrcBakedData*)loader_data_for_baked_src;
         FT_Activate_Size(bd_baked_data->FtSize);
         bd_font_data->BakedLastActivated = baked;
     }
@@ -618,6 +599,7 @@ const ImFontLoader* ImGuiFreeType::GetFontLoader()
     loader.FontBakedInit = ImGui_ImplFreeType_FontBakedInit;
     loader.FontBakedDestroy = ImGui_ImplFreeType_FontBakedDestroy;
     loader.FontBakedAddGlyph = ImGui_ImplFreeType_FontBakedAddGlyph;
+    loader.FontBakedSrcLoaderDataSize = sizeof(ImGui_ImplFreeType_FontSrcBakedData);
     return &loader;
 }