diff --git a/imgui.h b/imgui.h index e1d83d378..28e84e2a5 100644 --- a/imgui.h +++ b/imgui.h @@ -3444,7 +3444,9 @@ struct ImFontConfig // [Internal] char Name[40]; // Name (strictly to ease debugging) + ImFontFlags Flags; // Font flags (don't use just yet) ImFont* DstFont; // Target font (as we merging fonts, multiple ImFontConfig may target the same font) + const ImFontLoader* FontLoader; // Custom font backend for this source (other use one stored in ImFontAtlas) void* FontLoaderData; // Font loader opaque storage (per font config) IMGUI_API ImFontConfig(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ee88d5f8d..3106f2fe7 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2607,14 +2607,18 @@ ImFontAtlas::ImFontAtlas() ImFontAtlas::~ImFontAtlas() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!"); - Clear(); + RendererHasTextures = false; // Full Clear() is supported, but ClearTexData() only isn't. + ClearFonts(); + ClearTexData(); + TexList.clear_delete(); + TexData = NULL; } void ImFontAtlas::Clear() { - ClearFonts(); bool backup_renderer_has_textures = RendererHasTextures; RendererHasTextures = false; // Full Clear() is supported, but ClearTexData() only isn't. + ClearFonts(); ClearTexData(); if (Builder != NULL) ImFontAtlasBuildClearTexture(this); @@ -2631,8 +2635,9 @@ void ImFontAtlas::ClearInputData() IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!"); for (ImFontConfig& font_cfg : Sources) { - if (FontLoader && FontLoader->FontSrcDestroy != NULL) - FontLoader->FontSrcDestroy(this, &font_cfg); + const ImFontLoader* loader = font_cfg.FontLoader ? font_cfg.FontLoader : FontLoader; + if (loader && loader->FontSrcDestroy != NULL) + loader->FontSrcDestroy(this, &font_cfg); if (font_cfg.FontData && font_cfg.FontDataOwnedByAtlas) { IM_FREE(font_cfg.FontData); @@ -2957,7 +2962,7 @@ bool ImFontAtlas::Build() ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!"); - IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0); + IM_ASSERT((font_cfg->FontData != NULL && font_cfg->FontDataSize > 0) || (font_cfg->FontLoader != NULL)); IM_ASSERT(font_cfg->SizePixels > 0.0f && "Is ImFontConfig struct correctly initialized?"); IM_ASSERT(font_cfg->RasterizerDensity > 0.0f && "Is ImFontConfig struct correctly initialized?"); @@ -2971,6 +2976,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) { font = IM_NEW(ImFont)(); font->FontId = FontNextUniqueID++; + font->Flags = font_cfg->Flags; Fonts.push_back(font); } else @@ -2998,6 +3004,9 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) IM_ASSERT((size & 1) == 0 && "GlyphExcludeRanges[] size must be multiple of two!"); IM_ASSERT((size <= 64) && "GlyphExcludeRanges[] size must be small!"); } + if (font_cfg->FontLoader != NULL) + IM_ASSERT(font_cfg->FontLoader->FontBakedAddGlyph != NULL); + IM_ASSERT(font_cfg->FontLoaderData == NULL); // Round font size // - We started rounding in 1.90 WIP (18991) as our layout system currently doesn't support non-rounded font size well yet. @@ -3165,8 +3174,9 @@ void ImFontAtlas::RemoveFont(ImFont* font) for (int src_n = 0; src_n < font->SourcesCount; src_n++) { ImFontConfig* src = (ImFontConfig*)(void*)&font->Sources[src_n]; - if (FontLoader && FontLoader->FontSrcDestroy != NULL) - FontLoader->FontSrcDestroy(this, src); + const ImFontLoader* loader = src->FontLoader ? src->FontLoader : FontLoader; + if (loader && loader->FontSrcDestroy != NULL) + loader->FontSrcDestroy(this, src); if (src->FontData != NULL && src->FontDataOwnedByAtlas) IM_FREE(src->FontData); } @@ -3317,6 +3327,8 @@ void ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, float size, int* ou *out_oversample_v = (src->OversampleV != 0) ? src->OversampleV : 1; } +// Setup main font loader for the atlas +// Every font source (ImFontConfig) will use this unless ImFontConfig::FontLoader specify a custom loader. void ImFontAtlasBuildSetupFontLoader(ImFontAtlas* atlas, const ImFontLoader* font_loader) { if (atlas->FontLoader == font_loader) @@ -3521,9 +3533,10 @@ bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src) IM_ASSERT(font->Sources == src); } - const ImFontLoader* font_loader = atlas->FontLoader; - if (!font_loader->FontSrcInit(atlas, src)) - return false; + const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader; + if (loader->FontSrcInit != NULL) + if (!loader->FontSrcInit(atlas, src)) + return false; ImFontAtlasBuildSetupFontSpecialGlyphs(atlas, font, src); return true; @@ -3680,15 +3693,22 @@ ImFontBaked* ImFontAtlasBuildAddFontBaked(ImFontAtlas* atlas, ImFont* font, floa baked->LastUsedFrame = atlas->Builder->FrameCount; // Initialize backend data - size_t loader_data_size = font->SourcesCount * atlas->FontLoader->FontBakedSrcLoaderDataSize; + size_t loader_data_size = 0; + for (int src_n = 0; src_n < font->SourcesCount; src_n++) // Cannot easily be cached as we allow changing backend + { + ImFontConfig* src = &font->Sources[src_n]; + const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader; + loader_data_size += loader->FontBakedSrcLoaderDataSize; + } baked->FontLoaderDatas = (loader_data_size > 0) ? IM_ALLOC(loader_data_size) : NULL; - char* backend_user_data_p = (char*)baked->FontLoaderDatas; + char* loader_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; + const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader; + if (loader->FontBakedInit) + loader->FontBakedInit(atlas, src, baked, loader_data_p); + loader_data_p += loader->FontBakedSrcLoaderDataSize; } ImFontAtlasBuildSetupFontBakedSpecialGlyphs(atlas, baked->ContainerFont, baked); @@ -3704,13 +3724,14 @@ void ImFontAtlasBuildDiscardFontBaked(ImFontAtlas* atlas, ImFont* font, ImFontBa if (glyph.PackId >= 0) ImFontAtlasPackDiscardRect(atlas, glyph.PackId); - char* backend_user_data_p = (char*)baked->FontLoaderDatas; + char* loader_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; + const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader; + if (loader->FontBakedDestroy) + loader->FontBakedDestroy(atlas, src, baked, loader_data_p); + loader_data_p += loader->FontBakedSrcLoaderDataSize; } if (baked->FontLoaderDatas) { @@ -4094,9 +4115,12 @@ void ImFontAtlasBuildDestroy(ImFontAtlas* atlas) { for (ImFont* font : atlas->Fonts) font->ClearOutputData(); - if (atlas->FontLoader && atlas->FontLoader->FontSrcDestroy != NULL) - for (ImFontConfig& font_cfg : atlas->Sources) - atlas->FontLoader->FontSrcDestroy(atlas, &font_cfg); + for (ImFontConfig& font_cfg : atlas->Sources) + { + const ImFontLoader* loader = font_cfg.FontLoader ? font_cfg.FontLoader : atlas->FontLoader; + if (loader && loader->FontSrcDestroy != NULL) + loader->FontSrcDestroy(atlas, &font_cfg); + } IM_DELETE(atlas->Builder); atlas->Builder = NULL; @@ -4258,19 +4282,19 @@ ImFontGlyph* ImFontBaked::BuildLoadGlyph(ImWchar codepoint) ImFontConfig* srcs = (font->LockSingleSrcConfigIdx != -1) ? &font->Sources[font->LockSingleSrcConfigIdx] : font->Sources; // Call backend - const ImFontLoader* font_loader = atlas->FontLoader; - char* backend_user_data_p = (char*)baked->FontLoaderDatas; + char* loader_user_data_p = (char*)baked->FontLoaderDatas; for (int src_n = 0; src_n < srcs_count; src_n++) { ImFontConfig* src = &srcs[src_n]; + const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader; if (!src->GlyphExcludeRanges || ImFontAtlasBuildAcceptCodepointForSource(src, codepoint)) - if (font_loader->FontBakedAddGlyph(atlas, src, baked, backend_user_data_p, codepoint)) + if (loader->FontBakedAddGlyph(atlas, src, baked, loader_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; + loader_user_data_p += loader->FontBakedSrcLoaderDataSize; } // Mark index as not found, so we don't attempt the search twice @@ -5017,8 +5041,12 @@ bool ImFont::IsGlyphInFont(ImWchar c) { ImFontAtlas* atlas = ContainerAtlas; for (int src_n = 0; src_n < SourcesCount; src_n++) - if (atlas->FontLoader->FontSrcContainsGlyph(atlas, &Sources[src_n], c)) + { + ImFontConfig* src = &Sources[src_n]; + const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader; + if (loader->FontSrcContainsGlyph != NULL && loader->FontSrcContainsGlyph(atlas, src, c)) return true; + } return false; }