Add `ImFontLoader::FontAddFallbackSrc` for loading fallback fonts dynamically
This adds a hook for backends to lookup fallback fonts from the user's system when encountering a missing glyph and merge them to the current ImFont on demand.
static const char *ResolveSystemFont(BackendDetails *, const ImWchar codepoint, unsigned int *index)
{
return ...; // eg. using FontConfig or DirectWrite
}
static void LookupFallbackFont(ImFontAtlas *atlas, ImFont *font, const ImWchar codepoint)
{
auto details {static_cast<BackendDetails *>(font->Sources.front()->UserData)};
ImFontConfig cfg;
cfg.UserData = details; // added as a convenience to quickly map ImFont -> backend impl details
cfg.MergeTarget = font; // replaces `MergeMode = true` to merge with any font not just the last added one
// zero or more sources may be added here (they'll be initialized across all baked instances as long as MergeTarget == font)
if(const char *fallback_file {ResolveSystemFont(details, codepoint, &cfg.FontNo)})
atlas->AddFontFromFileTTF(fallback_file, 0, &cfg);
}
void Setup()
{
static auto loader {*ImGuiFreeType::GetFontLoader()};
loader.FontAddFallbackSrc = &LookupFallbackFont;
atlas->SetFontLoader(&loader);
}
I will definitively want to merge such feature, but I believe it needs to wait until I refactor font adding/loading functions and memory ownership, so I am putting to likely put that on hold for a bit.
There's actually a sort of "regression" in 1.92.0 as we keep font data in RAM and they may be loaded multiple times, which is an incredible waste. We are going to switch to a model where the library keeps a dictionary of unique data blob for fonts.
Also, since missing glyphs are cached per-baked font, it unnecessarily retries every time the font size changes (eg. auto-scaling). (Requiring the backend's fallback hook to do its own caching on top.)
I will definitively want to merge such feature, but I believe it needs to wait until I refactor font adding/loading functions and memory ownership, so I am putting to likely put that on hold for a bit.
There's actually a sort of "regression" in 1.92.0 as we keep font data in RAM and they may be loaded multiple times, which is an incredible waste. We are going to switch to a model where the library keeps a dictionary of unique data blob for fonts.
Technically speaking this can likely be exposed with a simple flag e.g. ImFontFlags_DeferLoading but however the data source is loaded and referenced is the important backbone part of it. I imagine we might make a ImFontSrc be provided e.g a data pointer or a function callback.
I may get back to this sooner as I am presently trying to figure out which is the preferred order to tackle incoming font changes.