From 59a11363a52071b438043e35c0865f377b630d43 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 26 May 2025 23:13:34 +0200 Subject: [PATCH] Fonts: ground work for allowing SizePixels to be optional. --- imgui.cpp | 5 ++++- imgui.h | 4 ++-- imgui_draw.cpp | 11 ++++++++--- misc/freetype/imgui_freetype.cpp | 3 ++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d18beab96..1ffa0652f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1204,6 +1204,9 @@ CODE #define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Hold CTRL to display for all candidates. CTRL+Arrow to change last direction. #define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window +// Default font size if unspecified in both style.FontSizeBase and AddFontXXX() calls. +static const float FONT_DEFAULT_SIZE = 20.0f; + // When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear @@ -8635,7 +8638,7 @@ void ImGui::UpdateFontsNewFrame() // Apply default font size the first time ImFont* font = ImGui::GetDefaultFont(); if (g.Style.FontSizeBase <= 0.0f) - g.Style.FontSizeBase = font->LegacySize * g.Style._MainScale; + g.Style.FontSizeBase = (font->LegacySize > 0.0f ? font->LegacySize : FONT_DEFAULT_SIZE) * g.Style._MainScale; // Set initial font g.Font = font; diff --git a/imgui.h b/imgui.h index d2bc7ce77..6e99b0be9 100644 --- a/imgui.h +++ b/imgui.h @@ -3475,10 +3475,10 @@ struct ImFontConfig ImVec2 GlyphOffset; // 0, 0 // Offset (in pixels) all glyphs from this font input. Absolute value for default size, other sizes will scale this value. float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font. Absolute value for default size, other sizes will scale this value. float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs - float GlyphExtraAdvanceX; // 0 // Extra spacing (in pixels) between glyphs. Please contact us if you are using this. + float GlyphExtraAdvanceX; // 0 // Extra spacing (in pixels) between glyphs. Please contact us if you are using this. // FIXME-NEWATLAS: Intentionally unscaled unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure. float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future. - float RasterizerDensity; // 1.0f // (Legacy: this only makes sense when ImGuiBackendFlags_RendererHasTextures is not supported). DPI scale multiplier for rasterization. Not altering other font metrics: makes it easy to swap between e.g. a 100% and a 400% fonts for a zooming display, or handle Retina screen. IMPORTANT: If you change this it is expected that you increase/decrease font scale roughly to the inverse of this, otherwise quality may look lowered. + float RasterizerDensity; // 1.0f // [LEGACY: this only makes sense when ImGuiBackendFlags_RendererHasTextures is not supported] DPI scale multiplier for rasterization. Not altering other font metrics: makes it easy to swap between e.g. a 100% and a 400% fonts for a zooming display, or handle Retina screen. IMPORTANT: If you change this it is expected that you increase/decrease font scale roughly to the inverse of this, otherwise quality may look lowered. ImWchar EllipsisChar; // 0 // Explicitly specify Unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. // [Internal] diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e74477dc6..6fabbac9e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2988,10 +2988,13 @@ bool ImFontAtlas::Build() ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in) { + // Sanity Checks IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!"); IM_ASSERT((font_cfg_in->FontData != NULL && font_cfg_in->FontDataSize > 0) || (font_cfg_in->FontLoader != NULL)); - IM_ASSERT(font_cfg_in->SizePixels > 0.0f && "Is ImFontConfig struct correctly initialized?"); + //IM_ASSERT(font_cfg_in->SizePixels > 0.0f && "Is ImFontConfig struct correctly initialized?"); IM_ASSERT(font_cfg_in->RasterizerDensity > 0.0f && "Is ImFontConfig struct correctly initialized?"); + if (font_cfg_in->GlyphOffset.x != 0.0f || font_cfg_in->GlyphOffset.y != 0.0f || font_cfg_in->GlyphMinAdvanceX != 0.0f || font_cfg_in->GlyphMaxAdvanceX != FLT_MAX) + IM_ASSERT(font_cfg_in->SizePixels != 0.0f && "Specifying glyph offset/advances requires a reference size to base it on."); // Lazily create builder on the first call to AddFont if (Builder == NULL) @@ -4636,7 +4639,8 @@ static bool ImGui_ImplStbTrueType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontC if (oversample_v > 1) stbtt__v_prefilter(bitmap_pixels, r->w, r->h, r->w, oversample_v); - const float offsets_scale = baked->Size / baked->ContainerFont->Sources[0]->SizePixels; + const float ref_size = baked->ContainerFont->Sources[0]->SizePixels; + const float offsets_scale = (ref_size != 0.0f) ? (baked->Size / ref_size) : 1.0f; float font_off_x = (src->GlyphOffset.x * offsets_scale); float font_off_y = (src->GlyphOffset.y * offsets_scale); if (src->PixelSnapH) // Snap scaled offset. This is to mitigate backward compatibility issues for GlyphOffset, but a better design would be welcome. @@ -5075,7 +5079,8 @@ ImFontGlyph* ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked if (src != NULL) { // Clamp & recenter if needed - const float offsets_scale = baked->Size / baked->ContainerFont->Sources[0]->SizePixels; + const float ref_size = baked->ContainerFont->Sources[0]->SizePixels; + const float offsets_scale = (ref_size != 0.0f) ? (baked->Size / ref_size) : 1.0f; float advance_x = ImClamp(glyph->AdvanceX, src->GlyphMinAdvanceX * offsets_scale, src->GlyphMaxAdvanceX * offsets_scale); if (advance_x != glyph->AdvanceX) { diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index a0fc96926..4c10ff42d 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -527,7 +527,8 @@ bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConfig* src uint32_t* temp_buffer = (uint32_t*)atlas->Builder->TempBuffer.Data; ImGui_ImplFreeType_BlitGlyph(ft_bitmap, temp_buffer, w); - const float offsets_scale = baked->Size / baked->ContainerFont->Sources[0]->SizePixels; + const float ref_size = baked->ContainerFont->Sources[0]->SizePixels; + const float offsets_scale = (ref_size != 0.0f) ? (baked->Size / ref_size) : 1.0f; float font_off_x = (src->GlyphOffset.x * offsets_scale); float font_off_y = (src->GlyphOffset.y * offsets_scale) + baked->Ascent; if (src->PixelSnapH) // Snap scaled offset. This is to mitigate backward compatibility issues for GlyphOffset, but a better design would be welcome.