Fonts: ClearCache(), ImFontAtlasBuildGetTextureSizeEstimate(), tweak clearing functions.

This commit is contained in:
ocornut
2025-06-11 15:43:06 +02:00
parent ef1521b472
commit 4399599de9
3 changed files with 47 additions and 28 deletions
+4 -4
View File
@@ -3523,12 +3523,12 @@ struct ImFontAtlas
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
// FIXME-NEWATLAS: Clarify meaning/purpose // FIXME-NEWATLAS: Clarify meaning/purpose
IMGUI_API void ClearInputData(); // Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
IMGUI_API void ClearFonts(); // Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).
IMGUI_API void ClearTexData(); // Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory.
IMGUI_API void Clear(); // Clear all input and output. IMGUI_API void Clear(); // Clear all input and output.
IMGUI_API void ClearCache(); // Clear cached glyphs IMGUI_API void ClearCache(); // Clear cached glyphs
// As we are transitioning toward a new font system, we expect to obsolete those soon:
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
IMGUI_API void ClearFonts(); // [OBSOLETE] Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).
IMGUI_API void ClearTexData(); // [OBSOLETE] Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory.
// Build atlas, retrieve pixel data. // Build atlas, retrieve pixel data.
// User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID(). // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID().
+42 -24
View File
@@ -2569,8 +2569,9 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3
{ ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed { ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed
}; };
#define IM_FONTGLYPH_INDEX_UNUSED ((ImU16)-1) // 0xFFFF #define IM_FONTGLYPH_INDEX_UNUSED ((ImU16)-1) // 0xFFFF
#define IM_FONTGLYPH_INDEX_NOT_FOUND ((ImU16)-2) // 0xFFFE #define IM_FONTGLYPH_INDEX_NOT_FOUND ((ImU16)-2) // 0xFFFE
#define IM_FONTATLAS_DEFAULT_TEXTURE_SIZE ImVec2i(512, 128)
ImFontAtlas::ImFontAtlas() ImFontAtlas::ImFontAtlas()
{ {
@@ -2600,11 +2601,14 @@ void ImFontAtlas::ClearInputData()
// When clearing this we lose access to the font name and other information used to build the font. // When clearing this we lose access to the font name and other information used to build the font.
for (ImFont* font : Fonts) for (ImFont* font : Fonts)
{
if (font->Sources >= Sources.Data && font->Sources < Sources.Data + Sources.Size) if (font->Sources >= Sources.Data && font->Sources < Sources.Data + Sources.Size)
{ {
font->Sources = NULL; font->Sources = NULL;
font->SourcesCount = 0; font->SourcesCount = 0;
} }
font->LockDisableLoading = true;
}
Sources.clear(); Sources.clear();
//CustomRects.clear(); //CustomRects.clear();
// Important: we leave TexReady untouched // Important: we leave TexReady untouched
@@ -2616,15 +2620,14 @@ void ImFontAtlas::ClearTexData()
TexList.clear(); TexList.clear();
IM_DELETE(TexData); IM_DELETE(TexData);
TexData = NULL; TexData = NULL;
// TexData.Destroy(); // Important: we leave TexReady untouched
//IM_ASSERT(0);
// Important: we leave TexReady untouched
} }
void ImFontAtlas::ClearFonts() void ImFontAtlas::ClearFonts()
{ {
// FIXME-NEWATLAS: Illegal to remove currently bound font. // FIXME-NEWATLAS: Illegal to remove currently bound font.
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!"); IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
ImFontAtlasBuildDestroy(this);
ClearInputData(); ClearInputData();
Fonts.clear_delete(); Fonts.clear_delete();
TexIsBuilt = false; TexIsBuilt = false;
@@ -2637,7 +2640,7 @@ void ImFontAtlas::ClearFonts()
void ImFontAtlas::Clear() void ImFontAtlas::Clear()
{ {
//IM_DELETE(Builder); // FIXME-NEW-ATLAS: ClearXXX functions //IM_DELETE(Builder); // FIXME-NEW-ATLAS: Clarify ClearXXX functions
const ImFontLoader* font_loader = FontLoader; const ImFontLoader* font_loader = FontLoader;
ImFontAtlasBuildSetupFontLoader(this, NULL); ImFontAtlasBuildSetupFontLoader(this, NULL);
ClearInputData(); ClearInputData();
@@ -2649,11 +2652,9 @@ void ImFontAtlas::Clear()
// FIXME-NEWATLAS: Too widespread purpose. Clarify each call site in current WIP demo. // FIXME-NEWATLAS: Too widespread purpose. Clarify each call site in current WIP demo.
void ImFontAtlas::ClearCache() void ImFontAtlas::ClearCache()
{ {
int tex_w = (TexData && TexData->Status != ImTextureStatus_WantDestroy) ? TexData->Width : 0; ImVec2i new_tex_size = ImFontAtlasBuildGetTextureSizeEstimate(this);
int tex_h = (TexData && TexData->Status != ImTextureStatus_WantDestroy) ? TexData->Height : 0;
ImFontAtlasBuildDestroy(this); ImFontAtlasBuildDestroy(this);
if (tex_w != 0 && tex_h != 0) ImFontAtlasBuildAddTexture(this, new_tex_size.x, new_tex_size.y);
ImFontAtlasBuildAddTexture(this, tex_w, tex_h);
ImFontAtlasBuildInit(this); ImFontAtlasBuildInit(this);
} }
@@ -3139,6 +3140,13 @@ bool ImFontAtlas::Build()
{ {
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!"); IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
if (TexData && TexData->Format != TexDesiredFormat)
{
ImVec2i new_tex_size = ImFontAtlasBuildGetTextureSizeEstimate(this);
ImFontAtlasBuildDestroy(this);
ImFontAtlasBuildAddTexture(this, new_tex_size.x, new_tex_size.y);
}
if (Builder == NULL) if (Builder == NULL)
ImFontAtlasBuildInit(this); ImFontAtlasBuildInit(this);
@@ -3168,7 +3176,10 @@ void ImFontAtlasBuildSetupFontLoader(ImFontAtlas* atlas, const ImFontLoader* fon
return; return;
IM_ASSERT(!atlas->Locked && "Cannot modify a locked ImFontAtlas!"); IM_ASSERT(!atlas->Locked && "Cannot modify a locked ImFontAtlas!");
// Note that texture size estimate is likely incorrect in this situation, as Freetype backend doesn't use oversampling.
ImVec2i new_tex_size = ImFontAtlasBuildGetTextureSizeEstimate(atlas);
ImFontAtlasBuildDestroy(atlas); ImFontAtlasBuildDestroy(atlas);
if (atlas->FontLoader && atlas->FontLoader->LoaderShutdown) if (atlas->FontLoader && atlas->FontLoader->LoaderShutdown)
{ {
atlas->FontLoader->LoaderShutdown(atlas); atlas->FontLoader->LoaderShutdown(atlas);
@@ -3178,8 +3189,9 @@ void ImFontAtlasBuildSetupFontLoader(ImFontAtlas* atlas, const ImFontLoader* fon
atlas->FontLoaderName = font_loader ? font_loader->Name : "NULL"; atlas->FontLoaderName = font_loader ? font_loader->Name : "NULL";
if (atlas->FontLoader && atlas->FontLoader->LoaderInit) if (atlas->FontLoader && atlas->FontLoader->LoaderInit)
atlas->FontLoader->LoaderInit(atlas); atlas->FontLoader->LoaderInit(atlas);
if (atlas->Builder && font_loader != NULL)
atlas->ClearCache(); ImFontAtlasBuildAddTexture(atlas, new_tex_size.x, new_tex_size.y);
ImFontAtlasBuildInit(atlas);
} }
// Preload all glyph ranges for legacy backends. // Preload all glyph ranges for legacy backends.
@@ -3684,17 +3696,13 @@ void ImFontAtlasBuildGrowTexture(ImFontAtlas* atlas, int old_tex_w, int old_tex_
ImFontAtlasBuildRepackTexture(atlas, new_tex_w, new_tex_h); ImFontAtlasBuildRepackTexture(atlas, new_tex_w, new_tex_h);
} }
// You should not need to call this manually! // FIXME-NEWATLAS: Expose atlas->TexMinWidth etc.
// If you think you do, let us know and we can advise about policies auto-compact. ImVec2i ImFontAtlasBuildGetTextureSizeEstimate(ImFontAtlas* atlas)
void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas)
{ {
if (atlas->Builder == NULL || atlas->TexData == NULL || atlas->TexData->Status == ImTextureStatus_WantDestroy)
return IM_FONTATLAS_DEFAULT_TEXTURE_SIZE;
ImFontAtlasBuilder* builder = atlas->Builder; ImFontAtlasBuilder* builder = atlas->Builder;
ImTextureData* old_tex = atlas->TexData;
int old_tex_w = old_tex->Width;
int old_tex_h = old_tex->Height;
// FIXME-NEWATLAS: Expose atlas->TexMinWidth etc.
const int min_w = ImMax(builder->MaxRectSize.x, 512); const int min_w = ImMax(builder->MaxRectSize.x, 512);
const int min_h = builder->MaxRectSize.y; const int min_h = builder->MaxRectSize.y;
const int surface_approx = atlas->_PackedSurface - builder->RectsDiscardedSurface; // Expected surface after repack const int surface_approx = atlas->_PackedSurface - builder->RectsDiscardedSurface; // Expected surface after repack
@@ -3716,11 +3724,21 @@ void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas)
new_tex_h = ImUpperPowerOfTwo(new_tex_h); new_tex_h = ImUpperPowerOfTwo(new_tex_h);
new_tex_w = ImMax(min_w, (int)((surface_approx + new_tex_h - 1) / new_tex_h)); new_tex_w = ImMax(min_w, (int)((surface_approx + new_tex_h - 1) / new_tex_h));
} }
return ImVec2i(new_tex_w, new_tex_h);
}
if (builder->RectsDiscardedCount == 0 && new_tex_w == old_tex_w && new_tex_h == old_tex_h) // You should not need to call this manually!
// If you think you do, let us know and we can advise about policies auto-compact.
void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas)
{
ImFontAtlasBuilder* builder = atlas->Builder;
ImTextureData* old_tex = atlas->TexData;
ImVec2i old_tex_size = ImVec2i(old_tex->Width, old_tex->Height);
ImVec2i new_tex_size = ImFontAtlasBuildGetTextureSizeEstimate(atlas);
if (builder->RectsDiscardedCount == 0 && new_tex_size.x == old_tex_size.x && new_tex_size.y == old_tex_size.y)
return; return;
ImFontAtlasBuildRepackTexture(atlas, new_tex_w, new_tex_h); ImFontAtlasBuildRepackTexture(atlas, new_tex_size.x, new_tex_size.y);
} }
// Start packing over current empty texture // Start packing over current empty texture
@@ -3745,7 +3763,7 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
} }
// Create initial texture size // Create initial texture size
if (atlas->TexData == NULL) if (atlas->TexData == NULL)
ImFontAtlasBuildAddTexture(atlas, 512, 128); ImFontAtlasBuildAddTexture(atlas, IM_FONTATLAS_DEFAULT_TEXTURE_SIZE.x, IM_FONTATLAS_DEFAULT_TEXTURE_SIZE.y);
const bool builder_is_new = (builder == NULL); const bool builder_is_new = (builder == NULL);
if (builder_is_new) if (builder_is_new)
+1
View File
@@ -3712,6 +3712,7 @@ IMGUI_API ImTextureData* ImFontAtlasBuildAddTexture(ImFontAtlas* atlas, int w
IMGUI_API void ImFontAtlasBuildRepackTexture(ImFontAtlas* atlas, int w, int h); 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 ImFontAtlasBuildGrowTexture(ImFontAtlas* atlas, int old_w = -1, int old_h = -1);
IMGUI_API void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas);
IMGUI_API ImVec2i ImFontAtlasBuildGetTextureSizeEstimate(ImFontAtlas* atlas);
IMGUI_API bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src); IMGUI_API bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src);
IMGUI_API void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFontConfig* src); IMGUI_API void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFontConfig* src);