New macOS specific default font selection in 1.93.0 is a tad bit confusing. #9591

Open
opened 2026-10-17 10:23:22 +00:00 by floooh · 8 comments
floooh commented 2026-10-17 10:23:22 +00:00 (Migrated from github.com)

Version/Branch of Dear ImGui:

Version 1.93.0

Back-ends:

custom (sokol_imgui.h)

Compiler, OS:

macOS + Apple Clang

Description

I was just bitten by the new default font selection heuristic on macOS.

Basically, when Dear ImGui doesn't have enough information on startup yet, it expects that macOS backends render into high resolution displays and picks a different default font which would look bad for low resolution displays.

I guess it's fine to pick a different default font if not enough information is available, my only gripe is that it only happens on macOS, which led me down a confusing rabbit hole because text rendering looked broken on macOS when rendering to a half resolution framebuffer (which is the default in sokol when on high-dpi displays), while font rendering looked perfectly crisp on a low-res display on Windows.

E.g. "how can this happen, Dear ImGui only ever knows the framebuffer size and dpi scale, and that's the same in those two scenarios". I didn't expect that Dear ImGui has a sneaky macOS specific code path in the initialization.

TL;DR: I will deal with the problem somehow on my side, but I really wonder if this Mac-specific hack makes sense :)

PS: I think I would prefer a simple toggle during setup which switches the 'auto-font-selection' on or off, I'll try to add such an explicit toggle to sokol_imgui.h (with the default being off to emulate the previous behaviour). But I think even with such an "auto-select on/off" I would prefer that there's no Mac-specific hack in the GetExpectedContextFontSize function :) nvm - a new init-toggle is a stupid idea in hindsight, see my latest comment

### Version/Branch of Dear ImGui: Version 1.93.0 ### Back-ends: custom (sokol_imgui.h) ### Compiler, OS: macOS + Apple Clang ### Description I was just bitten by the new default font selection heuristic on macOS. Basically, when Dear ImGui doesn't have enough information on startup yet, it expects that macOS backends render into high resolution displays and picks a different default font which would look bad for low resolution displays. I guess it's fine to pick a different default font if not enough information is available, my only gripe is that it only happens on macOS, which led me down a confusing rabbit hole because text rendering looked broken on macOS when rendering to a half resolution framebuffer (which is the default in sokol when on high-dpi displays), while font rendering looked perfectly crisp on a low-res display on Windows. E.g. "how can this happen, Dear ImGui only ever knows the framebuffer size and dpi scale, and that's the same in those two scenarios". I didn't expect that Dear ImGui has a sneaky macOS specific code path in the initialization. TL;DR: I will deal with the problem somehow on my side, but I really wonder if this Mac-specific hack makes sense :) ~~PS: I think I would prefer a simple toggle during setup which switches the 'auto-font-selection' on or off, I'll try to add such an explicit toggle to sokol_imgui.h (with the default being off to emulate the previous behaviour). But I think even with such an "auto-select on/off" I would prefer that there's no Mac-specific hack in the `GetExpectedContextFontSize` function :)~~ nvm - a new init-toggle is a stupid idea in hindsight, see my latest comment
floooh commented 2026-10-17 11:05:18 +00:00 (Migrated from github.com)

Ok... I fixed it differently now in sokol_imgui.h without changing the public API, and in a way that's expected by Dear ImGui...

...basically simply initializing IO.DisplaySize and IO.DisplayFramebufferScale with the same values that would be fed into Dear ImGui at the start of a frame (before calling AddFontDefault. That way, the bitmap-font is chosen again in sokol's default case (rendering to half-res framebuffers when on a high-dpi display, while automatically picking the TTF font in a high-dpi rendering situation).

So from my POV, this ticket can be closed (but I wonder if other people will stumble over the same issue, or whether sokol is an outlier - and tbh, inverting the default for rendering to half-res vs native resolution is somewhere down my mental roadmap... it was justified on Intel Macs, but probably no longer on modern devices which have enough fillrate oompf).

Ok... I fixed it differently now in sokol_imgui.h without changing the public API, and in a way that's expected by Dear ImGui... ...basically simply initializing `IO.DisplaySize` and `IO.DisplayFramebufferScale` with the same values that would be fed into Dear ImGui at the start of a frame (before calling `AddFontDefault`. That way, the bitmap-font is chosen again in sokol's default case (rendering to half-res framebuffers when on a high-dpi display, while automatically picking the TTF font in a high-dpi rendering situation). So from my POV, this ticket can be closed (but I wonder if other people will stumble over the same issue, or whether sokol is an outlier - and tbh, inverting the default for rendering to half-res vs native resolution is somewhere down my mental roadmap... it was justified on Intel Macs, but probably no longer on modern devices which have enough fillrate oompf).
floooh commented 2026-10-17 11:05:18 +00:00 (Migrated from github.com)

Ok... I fixed it differently now in sokol_imgui.h without changing the public API, and in a way that's expected by Dear ImGui...

...basically simply initializing IO.DisplaySize and IO.DisplayFramebufferScale with the same values that would be fed into Dear ImGui at the start of a frame (before calling AddFontDefault. That way, the bitmap-font is chosen again in sokol's default case (rendering to half-res framebuffers when on a high-dpi display, while automatically picking the TTF font in a high-dpi rendering situation).

So from my POV, this ticket can be closed (but I wonder if other people will stumble over the same issue, or whether sokol is an outlier - and tbh, inverting the default for rendering to half-res vs native resolution is somewhere down my mental roadmap... it was justified on Intel Macs, but probably no longer on modern devices which have enough fillrate oompf).

Ok... I fixed it differently now in sokol_imgui.h without changing the public API, and in a way that's expected by Dear ImGui... ...basically simply initializing `IO.DisplaySize` and `IO.DisplayFramebufferScale` with the same values that would be fed into Dear ImGui at the start of a frame (before calling `AddFontDefault`. That way, the bitmap-font is chosen again in sokol's default case (rendering to half-res framebuffers when on a high-dpi display, while automatically picking the TTF font in a high-dpi rendering situation). So from my POV, this ticket can be closed (but I wonder if other people will stumble over the same issue, or whether sokol is an outlier - and tbh, inverting the default for rendering to half-res vs native resolution is somewhere down my mental roadmap... it was justified on Intel Macs, but probably no longer on modern devices which have enough fillrate oompf).
floooh commented 2026-10-17 11:12:35 +00:00 (Migrated from github.com)

E.g. after the fix (by providing the size- and scale-params upfront), sokol_imgui.h looks great again in low- and high-dpi on macOS:

Image Image
E.g. after the fix (by providing the size- and scale-params upfront), sokol_imgui.h looks great again in low- and high-dpi on macOS: <img width="438" height="153" alt="Image" src="https://github.com/user-attachments/assets/793e4f21-adae-4c42-8459-b1cbb0af8f89" /> <img width="557" height="174" alt="Image" src="https://github.com/user-attachments/assets/9cc999aa-4e9d-4807-9825-bef02e947ad5" />
floooh commented 2026-10-17 11:12:35 +00:00 (Migrated from github.com)

E.g. after the fix (by providing the size- and scale-params upfront), sokol_imgui.h looks great again in low- and high-dpi on macOS:

Image Image
E.g. after the fix (by providing the size- and scale-params upfront), sokol_imgui.h looks great again in low- and high-dpi on macOS: <img width="438" height="153" alt="Image" src="https://github.com/user-attachments/assets/793e4f21-adae-4c42-8459-b1cbb0af8f89" /> <img width="557" height="174" alt="Image" src="https://github.com/user-attachments/assets/9cc999aa-4e9d-4807-9825-bef02e947ad5" />
floooh commented 2026-10-17 13:21:35 +00:00 (Migrated from github.com)

I changed the issue title to be a bit less on the nose ;)

E.g. TL;DR: the issue has been solved on my side, but I still think that the 'guessing' behaviour just for macOS for the expected font size might be confusing in multi-platform code. IMHO it would be better when the default font-selection would guess "consistently wrong" across all platforms instead of just on one specific platform, because then the issue is easier to identify and debug.

I changed the issue title to be a bit less on the nose ;) E.g. TL;DR: the issue has been solved on my side, but I still think that the 'guessing' behaviour just for macOS for the expected font size might be confusing in multi-platform code. IMHO it would be better when the default font-selection would guess "consistently wrong" across all platforms instead of just on one specific platform, because then the issue is easier to identify and debug.
floooh commented 2026-10-17 13:21:35 +00:00 (Migrated from github.com)

I changed the issue title to be a bit less on the nose ;)

E.g. TL;DR: the issue has been solved on my side, but I still think that the 'guessing' behaviour just for macOS for the expected font size might be confusing in multi-platform code. IMHO it would be better when the default font-selection would guess "consistently wrong" across all platforms instead of just on one specific platform, because then the issue is easier to identify and debug.

I changed the issue title to be a bit less on the nose ;) E.g. TL;DR: the issue has been solved on my side, but I still think that the 'guessing' behaviour just for macOS for the expected font size might be confusing in multi-platform code. IMHO it would be better when the default font-selection would guess "consistently wrong" across all platforms instead of just on one specific platform, because then the issue is easier to identify and debug.
ocornut commented 2026-10-23 18:36:41 +00:00 (Migrated from github.com)

Sorry for my late answer, I have been away for a few days.

IMHO it would be better when the default font-selection would guess "consistently wrong" across all platforms instead of just on one specific platform, because then the issue is easier to identify and debug.

The problem is that given that Mac platform do not use ContentScale, it would always select the bitmap font, which is really substandard on macOS.

My thought was the opposite: if it picked the bitmap font, it wouldn't be "easier to identify and debug": it would just look blocky and you would expect this is how things are and not think about it. This makes dear imgui samples look worse by default, unless we decide to make them tackle specific font selection. Whereas by wrongly picking the vector font in your specific situation, you have a problem shown to you and you are more likely to investigate. I would also suggest that your situation is pretty unique, as you are developing a low-level framework and doing fairly unusual stuff.

For context, the code is:

// Legacy function with heuristic to select Pixel or Vector font.
// The selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi * io.DisplayFramebufferScale) reaching a small threshold at the time of adding the default font.
// Prefer calling AddFontDefaultVector() or AddFontDefaultBitmap() based on your own logic.
ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg)
{
    if (OwnerContext == NULL || GetExpectedContextFontSize(OwnerContext) >= 15.0f)
        return AddFontDefaultVector(font_cfg);
    else
        return AddFontDefaultBitmap(font_cfg);
}

// This duplicates some of the logic in UpdateFontsNewFrame() which is a bit chicken-and-eggy/tricky to extract due to variety of codepaths and possible initialization ordering.
static float GetExpectedContextFontSize(ImGuiContext* ctx)
{
    float fb_scale = (ctx->IO.DisplayFramebufferScale.x != 0.0f) ? ctx->IO.DisplayFramebufferScale.x : 1.0f;
    if (ctx->IO.DisplayFramebufferScale.x == 1.0f && ctx->IO.DisplaySize.x <= 0.0f && ctx->IO.ConfigMacOSXBehaviors)
        fb_scale = 2.0f; // If called before backend had a chance to init DisplayFramebufferScale. default to expecting Retina.
    float scale = ctx->Style.FontScaleMain * ctx->Style.FontScaleDpi * fb_scale;
    return ((ctx->Style.FontSizeBase > 0.0f) ? ctx->Style.FontSizeBase : 13.0f) * scale;
}

I've been struggling to find a better solution tbh.
I guess I wish the vector font looked better at small size and without FreeType, but it doesn't.

An idea: we could record that we picked this default font using the heuristic, and compare data on frame 1 to see if the heuristic still match, and emit some sort of feedback if it has changed. But even that tbh is tricky: we are not used to "spam" information. The easiest way to publish this information is to have it visible in Demo/Metrics panels.

About your now strike-through text saying:

PS: I think I would prefer a simple toggle during setup which switches the 'auto-font-selection' on or off, I'll try to add such an explicit toggle

You wouldn't have discovered it anyhow, or at least not faster than it took you to discover that an implicit AddFontDefault() was selecting a font among two.

Sorry for my late answer, I have been away for a few days. > IMHO it would be better when the default font-selection would guess "consistently wrong" across all platforms instead of just on one specific platform, because then the issue is easier to identify and debug. The problem is that given that Mac platform do not use ContentScale, it would always select the bitmap font, which is really substandard on macOS. My thought was the opposite: if it picked the bitmap font, it wouldn't be "easier to identify and debug": it would just look blocky and you would expect this is how things are and not think about it. This makes dear imgui samples look worse by default, unless we decide to make them tackle specific font selection. Whereas by wrongly picking the vector font in your specific situation, you have a problem shown to you and you are more likely to investigate. I would also suggest that your situation is pretty unique, as you are developing a low-level framework and doing fairly unusual stuff. For context, the code is: ```cpp // Legacy function with heuristic to select Pixel or Vector font. // The selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi * io.DisplayFramebufferScale) reaching a small threshold at the time of adding the default font. // Prefer calling AddFontDefaultVector() or AddFontDefaultBitmap() based on your own logic. ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg) { if (OwnerContext == NULL || GetExpectedContextFontSize(OwnerContext) >= 15.0f) return AddFontDefaultVector(font_cfg); else return AddFontDefaultBitmap(font_cfg); } // This duplicates some of the logic in UpdateFontsNewFrame() which is a bit chicken-and-eggy/tricky to extract due to variety of codepaths and possible initialization ordering. static float GetExpectedContextFontSize(ImGuiContext* ctx) { float fb_scale = (ctx->IO.DisplayFramebufferScale.x != 0.0f) ? ctx->IO.DisplayFramebufferScale.x : 1.0f; if (ctx->IO.DisplayFramebufferScale.x == 1.0f && ctx->IO.DisplaySize.x <= 0.0f && ctx->IO.ConfigMacOSXBehaviors) fb_scale = 2.0f; // If called before backend had a chance to init DisplayFramebufferScale. default to expecting Retina. float scale = ctx->Style.FontScaleMain * ctx->Style.FontScaleDpi * fb_scale; return ((ctx->Style.FontSizeBase > 0.0f) ? ctx->Style.FontSizeBase : 13.0f) * scale; } ``` I've been struggling to find a better solution tbh. I guess I wish the vector font looked better at small size and without FreeType, but it doesn't. An idea: we could record that we picked this default font using the heuristic, and compare data on frame 1 to see if the heuristic still match, and emit some sort of feedback if it has changed. But even that tbh is tricky: we are not used to "spam" information. The easiest way to publish this information is to have it visible in Demo/Metrics panels. About your now strike-through text saying: > PS: I think I would prefer a simple toggle during setup which switches the 'auto-font-selection' on or off, I'll try to add such an explicit toggle You wouldn't have discovered it anyhow, or at least not faster than it took you to discover that an implicit `AddFontDefault()` was selecting a font among two.
floooh commented 2026-10-24 11:22:16 +00:00 (Migrated from github.com)

Yeah agreed with all you said. I wouldn't go with your idea of checking again in frame 1, that just makes the under-the-hood behaviour more complex for not much gain.

I'm now communicating the relevant details for font selection to Dear ImGui before the default font is added, and that also fixes the issue in a way I'm happy with. There's only one situation where this might lead to the "wrong" font being selected, but that is too esoteric to worry about: when the default params (taken from the "default swapchain") select the TTF font, but then the UI is actually rendered into a low-resolution offscreen render target. But this could also be fixed on my side by requiring more init-parameters to be provided into the sokol-dear-imgui-backend initialization... but as I said, it's such an esoteric case that I don't worry about it.

Arguably the Dear ImGui backend in sokol_imgui.h could also delegate the font selection completely to the user (currently I add the default font as convenience, but the user may disable this behaviour).

Anyway... I think the ticket can be closed with "won't fix". Thanks for taking the time to write down your thoughts on the topic.

Yeah agreed with all you said. I wouldn't go with your idea of checking again in frame 1, that just makes the under-the-hood behaviour more complex for not much gain. I'm now communicating the relevant details for font selection to Dear ImGui before the default font is added, and that also fixes the issue in a way I'm happy with. There's only one situation where this might lead to the "wrong" font being selected, but that is too esoteric to worry about: when the default params (taken from the "default swapchain") select the TTF font, but then the UI is actually rendered into a low-resolution offscreen render target. But this could also be fixed on my side by requiring more init-parameters to be provided into the sokol-dear-imgui-backend initialization... but as I said, it's such an esoteric case that I don't worry about it. Arguably the Dear ImGui backend in sokol_imgui.h could also delegate the font selection completely to the user (currently I add the default font as convenience, but the user may disable this behaviour). Anyway... I think the ticket can be closed with "won't fix". Thanks for taking the time to write down your thoughts on the topic.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ocornut/imgui#9591
No description provided.