1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-11 00:04:24 +00:00

Fonts: automatically set current rasterizer density to viewport density. Effectively should fix most things on macOS.

# Conflicts:
#	imgui.cpp
#	imgui.h
This commit is contained in:
ocornut 2025-05-16 18:04:44 +02:00
parent ea756ede16
commit 5ee9845559
4 changed files with 38 additions and 28 deletions

View file

@ -130,7 +130,7 @@ ImGui::PopFont();
**For advanced options create a ImFontConfig structure and pass it to the AddFont() function (it will be copied internally):**
```cpp
ImFontConfig config;
config.RasterizerDensity = 2.0f;
config.OversampleH = 1.0f;
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
```

View file

@ -4398,6 +4398,8 @@ static void SetCurrentWindow(ImGuiWindow* window)
g.CurrentDpiScale = 1.0f; // FIXME-DPI: WIP this is modified in docking
if (window)
{
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures)
g.FontRasterizerDensity = window->Viewport->FramebufferScale.x; // == SetFontRasterizerDensity()
ImGui::UpdateCurrentFontSize();
ImGui::NavUpdateCurrentWindowIsScrollPushableX();
}
@ -8699,7 +8701,8 @@ void ImGui::UpdateCurrentFontSize()
g.DrawListSharedData.FontScale = g.FontScale;
}
// FIXME-DPI: Not sure how to expose this. It may be automatically applied based on current viewport, if we had this information stored in viewport or monitor.
// Exposed in case user may want to override setting density.
// IMPORTANT: Begin()/End() is overriding density. Be considerate of this you change it.
void ImGui::SetFontRasterizerDensity(float rasterizer_density)
{
ImGuiContext& g = *GImGui;
@ -15240,6 +15243,7 @@ static void ImGui::UpdateViewportsNewFrame()
main_viewport->Flags = ImGuiViewportFlags_IsPlatformWindow | ImGuiViewportFlags_OwnedByApp;
main_viewport->Pos = ImVec2(0.0f, 0.0f);
main_viewport->Size = g.IO.DisplaySize;
main_viewport->FramebufferScale = g.IO.DisplayFramebufferScale;
for (ImGuiViewportP* viewport : g.Viewports)
{

13
imgui.h
View file

@ -2322,7 +2322,8 @@ struct ImGuiIO
ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Keyboard/Gamepad navigation options, etc.
ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend.
ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size). May change every frame.
ImVec2 DisplaySize; // <unset> // Main display size, in pixels (== GetMainViewport()->Size). May change every frame.
ImVec2 DisplayFramebufferScale; // = (1, 1) // Main display density. For retina display where window coordinates are different from framebuffer coordinates. This will affect font density + will end up in ImDrawData::FramebufferScale.
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. May change every frame.
float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.
const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions.
@ -2334,7 +2335,6 @@ struct ImGuiIO
float FontGlobalScale; // = 1.0f // Global scale all fonts
bool FontAllowUserScaling; // = false // [OBSOLETE] Allow user scaling text of individual window with CTRL+Wheel.
ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0].
ImVec2 DisplayFramebufferScale; // = (1, 1) // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale.
// Keyboard/Gamepad Navigation options
bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
@ -3341,7 +3341,7 @@ struct ImDrawData
ImVector<ImDrawList*> CmdLists; // Array of ImDrawList* to render. The ImDrawLists are owned by ImGuiContext and only pointed to from here.
ImVec2 DisplayPos; // Top-left position of the viewport to render (== top-left of the orthogonal projection matrix to use) (== GetMainViewport()->Pos for the main viewport, == (0.0) in most single-viewport applications)
ImVec2 DisplaySize; // Size of the viewport to render (== GetMainViewport()->Size for the main viewport, == io.DisplaySize in most single-viewport applications)
ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display.
ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Copied from viewport->FramebufferScale (== io.DisplayFramebufferScale for main viewport). Generally (1,1) on normal display, (2,2) on OSX with Retina display.
ImGuiViewport* OwnerViewport; // Viewport carrying the ImDrawData instance, might be of use to the renderer (generally not).
ImVector<ImTextureData*>* Textures; // List of textures to update. Most of the times the list is shared by all ImDrawData, has only 1 texture and it doesn't need any update. This almost always points to ImGui::GetPlatformIO().Textures[]. May be overriden or set to NULL if you want to manually update textures.
@ -3734,8 +3734,8 @@ enum ImFontFlags_
ImFontFlags_None = 0,
ImFontFlags_UseDefaultSize = 1 << 0, // Legacy compatibility: make PushFont() calls without explicit size use font->DefaultSize instead of current font size.
ImFontFlags_NoLoadError = 1 << 1, // Disable throwing an error/assert when calling AddFontXXX() with missing file/data. Calling code is expected to check AddFontXXX() return value.
ImFontFlags_NoLoadGlyphs = 1 << 2, // Disable loading new glyphs.
ImFontFlags_LockBakedSizes = 1 << 3, // Disable loading new baked sizes, disable garbage collecting current ones. e.g. if you want to lock a font to a single size.
ImFontFlags_NoLoadGlyphs = 1 << 2, // [Internal] Disable loading new glyphs.
ImFontFlags_LockBakedSizes = 1 << 3, // [Internal] Disable loading new baked sizes, disable garbage collecting current ones. e.g. if you want to lock a font to a single size. Important: if you use this to preload given sizes, consider the possibility of multiple font density used on Retina display.
};
// Font runtime data and rendering
@ -3766,7 +3766,7 @@ struct ImFont
// Methods
IMGUI_API ImFont();
IMGUI_API ~ImFont();
IMGUI_API ImFontBaked* GetFontBaked(float font_size); // Get or create baked data for given size
IMGUI_API ImFontBaked* GetFontBaked(float font_size, float density = -1.0f); // Get or create baked data for given size
IMGUI_API bool IsGlyphInFont(ImWchar c);
bool IsLoaded() const { return ContainerAtlas != NULL; }
const char* GetDebugName() const { return Sources.Size ? Sources[0]->Name : "<unknown>"; } // Fill ImFontConfig::Name.
@ -3832,6 +3832,7 @@ struct ImGuiViewport
ImGuiViewportFlags Flags; // See ImGuiViewportFlags_
ImVec2 Pos; // Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates)
ImVec2 Size; // Main Area: Size of the viewport.
ImVec2 FramebufferScale; // Density of the viewport for Retina display (always 1,1 on Windows, may be 2,2 etc on macOS/iOS). This will affect font rasterizer density.
ImVec2 WorkPos; // Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos)
ImVec2 WorkSize; // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size)

View file

@ -3786,25 +3786,28 @@ ImFontBaked* ImFontAtlasBakedAdd(ImFontAtlas* atlas, ImFont* font, float font_si
ImFontBaked* ImFontAtlasBakedGetClosestMatch(ImFontAtlas* atlas, ImFont* font, float font_size, float font_rasterizer_density)
{
ImFontAtlasBuilder* builder = atlas->Builder;
ImFontBaked* closest_larger_match = NULL;
ImFontBaked* closest_smaller_match = NULL;
for (int baked_n = 0; baked_n < builder->BakedPool.Size; baked_n++)
for (int step_n = 0; step_n < 2; step_n++)
{
ImFontBaked* baked = &builder->BakedPool[baked_n];
if (baked->ContainerFont != font || baked->WantDestroy)
continue;
if (baked->RasterizerDensity != font_rasterizer_density)
continue;
if (baked->Size > font_size && (closest_larger_match == NULL || baked->Size < closest_larger_match->Size))
closest_larger_match = baked;
if (baked->Size < font_size && (closest_smaller_match == NULL || baked->Size > closest_smaller_match->Size))
closest_smaller_match = baked;
ImFontBaked* closest_larger_match = NULL;
ImFontBaked* closest_smaller_match = NULL;
for (int baked_n = 0; baked_n < builder->BakedPool.Size; baked_n++)
{
ImFontBaked* baked = &builder->BakedPool[baked_n];
if (baked->ContainerFont != font || baked->WantDestroy)
continue;
if (step_n == 0 && baked->RasterizerDensity != font_rasterizer_density) // First try with same density
continue;
if (baked->Size > font_size && (closest_larger_match == NULL || baked->Size < closest_larger_match->Size))
closest_larger_match = baked;
if (baked->Size < font_size && (closest_smaller_match == NULL || baked->Size > closest_smaller_match->Size))
closest_smaller_match = baked;
}
if (closest_larger_match)
if (closest_smaller_match == NULL || (closest_larger_match->Size >= font_size * 2.0f && closest_smaller_match->Size > font_size * 0.5f))
return closest_larger_match;
if (closest_smaller_match)
return closest_smaller_match;
}
if (closest_larger_match)
if (closest_smaller_match == NULL || (closest_larger_match->Size >= font_size * 2.0f && closest_smaller_match->Size > font_size * 0.5f))
return closest_larger_match;
if (closest_smaller_match)
return closest_smaller_match;
return NULL;
}
@ -5195,7 +5198,7 @@ ImGuiID ImFontAtlasBakedGetId(ImGuiID font_id, float baked_size, float rasterize
}
// ImFontBaked pointers are valid for the entire frame but shall never be kept between frames.
ImFontBaked* ImFont::GetFontBaked(float size)
ImFontBaked* ImFont::GetFontBaked(float size, float density)
{
ImFontBaked* baked = LastBaked;
@ -5203,12 +5206,14 @@ ImFontBaked* ImFont::GetFontBaked(float size)
// - ImGui::PushFontSize() will already round, but other paths calling GetFontBaked() directly also needs it (e.g. ImFontAtlasBuildPreloadAllGlyphRanges)
size = ImGui::GetRoundedFontSize(size);
if (baked && baked->Size == size && baked->RasterizerDensity == CurrentRasterizerDensity)
if (density < 0.0f)
density = CurrentRasterizerDensity;
if (baked && baked->Size == size && baked->RasterizerDensity == density)
return baked;
ImFontAtlas* atlas = ContainerAtlas;
ImFontAtlasBuilder* builder = atlas->Builder;
baked = ImFontAtlasBakedGetOrAdd(atlas, this, size, CurrentRasterizerDensity);
baked = ImFontAtlasBakedGetOrAdd(atlas, this, size, density);
if (baked == NULL)
return NULL;
baked->LastUsedFrame = builder->FrameCount;