DrawList: apply current pixel density to DrawList's fringe scale. Added ImDrawList::_SetPixelDensity(). Reword FontRasterizerDensity as CurrentPixelDensity.

Amend 94a4322.

# Conflicts:
#	imgui.cpp
#	imgui.h
#	imgui_draw.cpp
#	imgui_internal.h
This commit is contained in:
ocornut
2026-08-03 19:11:05 +02:00
parent fdc1152281
commit 5108603789
5 changed files with 30 additions and 18 deletions

View File

@@ -51,7 +51,11 @@ Other Changes:
- Fonts:
- Reworked `AddFontDefault()` to use `io.DisplayFrameBufferScale` as part of the heuristic
to select `AddFontDefaultVector()` by default, effectively using ProggyForever instead of
ProggyClean on most Mac setups by default.
ProggyClean on most Apple/Retina setups by default.
- ImDrawList:
- Per-viewport FramebufferScale for Apple/Retina screen is applied to draw lists:
- AA Fringe is scaled accordingly.
- Circle and Curves tessellation error are scaled accordingly.
-----------------------------------------------------------------------

View File

@@ -4240,7 +4240,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
Font = NULL;
FontBaked = NULL;
FontSize = FontSizeBase = FontBakedScale = CurrentDpiScale = 0.0f;
FontRasterizerDensity = 1.0f;
CurrentPixelDensity = 1.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
if (shared_font_atlas == NULL)
IO.Fonts->OwnerContext = this;
@@ -4711,7 +4711,7 @@ static void SetCurrentWindow(ImGuiWindow* window)
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures)
{
ImGuiViewport* viewport = window->Viewport;
g.FontRasterizerDensity = (viewport->FramebufferScale.x != 0.0f) ? viewport->FramebufferScale.x : g.IO.DisplayFramebufferScale.x; // == SetFontRasterizerDensity()
g.CurrentPixelDensity = (viewport->FramebufferScale.x != 0.0f) ? viewport->FramebufferScale.x : g.IO.DisplayFramebufferScale.x; // == SetPixelDensity()
}
const bool backup_skip_items = window->SkipItems;
window->SkipItems = false;
@@ -5308,6 +5308,7 @@ static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t draw
if (viewport->BgFgDrawListsLastTimeActive[drawlist_no] != (float)g.Time)
{
draw_list->_ResetForNewFrame();
draw_list->_SetPixelDensity(viewport->FramebufferScale.x);
draw_list->PushTexture(g.IO.Fonts->TexRef);
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
viewport->BgFgDrawListsLastTimeActive[drawlist_no] = (float)g.Time;
@@ -5591,7 +5592,6 @@ static void SetupDrawListSharedData()
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
g.DrawListSharedData.InitialFringeScale = 1.0f; // FIXME-DPI: Change this for some DPI scaling experiments.
}
void ImGui::NewFrame()
@@ -8081,6 +8081,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Setup draw list and outer clipping rectangle
IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
window->DrawList->_SetPixelDensity(window->Viewport->FramebufferScale.x);
window->DrawList->PushTexture(g.Font->OwnerAtlas->TexRef);
PushClipRect(host_rect.Min, host_rect.Max, false);
@@ -9049,7 +9050,7 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
// - UnregisterFontAtlas() [Internal]
// - SetCurrentFont() [Internal]
// - UpdateCurrentFontSize() [Internal]
// - SetFontRasterizerDensity() [Internal]
// - SetPixelDensity() [Internal]
// - PushFont()
// - PopFont()
//-----------------------------------------------------------------------------
@@ -9242,7 +9243,7 @@ void ImGui::UpdateCurrentFontSize(float restore_font_size_after_scaling)
final_size = GetRoundedFontSize(final_size);
final_size = ImClamp(final_size, 1.0f, IMGUI_FONT_SIZE_MAX);
if (g.Font != NULL && (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures))
g.Font->CurrentRasterizerDensity = g.FontRasterizerDensity;
g.Font->CurrentRasterizerDensity = g.CurrentPixelDensity;
g.FontSize = final_size;
g.DrawListSharedData.FontSize = g.FontSize;
@@ -9266,13 +9267,13 @@ void ImGui::UpdateCurrentFontSize(float restore_font_size_after_scaling)
// 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)
void ImGui::SetPixelDensity(float pixel_density)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures);
if (g.FontRasterizerDensity == rasterizer_density)
if (g.CurrentPixelDensity == pixel_density)
return;
g.FontRasterizerDensity = rasterizer_density;
g.CurrentPixelDensity = pixel_density;
UpdateCurrentFontSize(0.0f);
}

View File

@@ -3346,7 +3346,8 @@ struct ImDrawList
ImVector<ImVec4> _ClipRectStack; // [Internal]
ImVector<ImTextureRef> _TextureStack; // [Internal]
ImVector<ImU8> _CallbacksDataBuf; // [Internal]
float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content
float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content.
float _InvFringeScale; // [internal] 1.0 / _FringeScale // FIXME: Consider renaming to _PixelDensity.
const char* _OwnerName; // Pointer to owner window's name for debugging
// If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData().
@@ -3480,6 +3481,7 @@ struct ImDrawList
// [Internal helpers]
IMGUI_API void _SetDrawListSharedData(ImDrawListSharedData* data);
IMGUI_API void _ResetForNewFrame();
IMGUI_API void _SetPixelDensity(float pixel_density);
IMGUI_API void _ClearFreeMemory();
IMGUI_API void _PopUnusedDrawCmd();
IMGUI_API void _TryMergeDrawCmds();

View File

@@ -396,7 +396,6 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
ImDrawListSharedData::ImDrawListSharedData()
{
memset((void*)this, 0, sizeof(*this));
InitialFringeScale = 1.0f;
for (int i = 0; i < IM_COUNTOF(ArcFastVtx); i++)
{
const float a = ((float)i * 2 * IM_PI) / (float)IM_COUNTOF(ArcFastVtx);
@@ -473,7 +472,7 @@ void ImDrawList::_ResetForNewFrame()
_Path.resize(0);
_Splitter.Clear();
CmdBuffer.push_back(ImDrawCmd());
_FringeScale = _Data->InitialFringeScale;
// Caller needs to bet _SetPixelDensity() as well.
}
void ImDrawList::_ClearFreeMemory()
@@ -655,6 +654,7 @@ void ImDrawList::_OnChangedVtxOffset()
int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const
{
// Automatic segment count
radius *= _InvFringeScale;
const int radius_idx = (int)(radius + 0.999f); // ceil to never reduce accuracy
if (radius_idx >= 0 && radius_idx < IM_COUNTOF(_Data->CircleSegmentCounts))
return _Data->CircleSegmentCounts[radius_idx]; // Use cached value
@@ -720,6 +720,12 @@ void ImDrawList::_SetTexture(ImTextureRef tex_ref)
_OnChangedTexture();
}
void ImDrawList::_SetPixelDensity(float pixel_density)
{
_FringeScale = 1.0f / pixel_density;
_InvFringeScale = pixel_density;
}
// Reserve space for a number of vertices and indices.
// You must finish filling your reserved data before calling PrimReserve() again, as it may reallocate or
// submit the intermediate results. PrimUnreserve() can be used to release unused allocations.
@@ -1419,7 +1425,7 @@ void ImDrawList::PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, cons
if (num_segments == 0)
{
IM_ASSERT(_Data->CurveTessellationMaxError > 0.0f);
float max_error_sqr = _Data->CurveTessellationMaxError * _Data->CurveTessellationMaxError;
float max_error_sqr = (_Data->CurveTessellationMaxError * _FringeScale) * (_Data->CurveTessellationMaxError * _FringeScale);
PathBezierCubicCurveToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, max_error_sqr, 0); // Auto-tessellated
}
else
@@ -1436,7 +1442,7 @@ void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3,
if (num_segments == 0)
{
IM_ASSERT(_Data->CurveTessellationMaxError > 0.0f);
float max_error_sqr = _Data->CurveTessellationMaxError * _Data->CurveTessellationMaxError;
float max_error_sqr = (_Data->CurveTessellationMaxError * _FringeScale) * (_Data->CurveTessellationMaxError * _FringeScale);
PathBezierQuadraticCurveToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, max_error_sqr, 0);// Auto-tessellated
}
else

View File

@@ -897,7 +897,6 @@ struct IMGUI_API ImDrawListSharedData
float FontScale; // Current font scale (== FontSize / Font->FontSize)
float CurveTessellationMaxError; // Tessellation tolerance when using PathBezierCurveTo()
float CircleTessellationMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
float InitialFringeScale; // Initial scale to apply to AA fringe
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
ImVector<ImVec2> TempBuffer; // Temporary write buffer
@@ -2267,7 +2266,7 @@ struct ImGuiContext
float FontSize; // Currently bound font size == line height (== FontSizeBase + externals scales applied in the UpdateCurrentFontSize() function).
float FontSizeBase; // Font size before scaling == style.FontSizeBase == value passed to PushFont() when specified.
float FontBakedScale; // == FontBaked->Size / FontSize. Scale factor over baked size. Rarely used nowadays, very often == 1.0f.
float FontRasterizerDensity; // Current font density. Used by all calls to GetFontBaked().
float CurrentPixelDensity; // Current font density. Used by all calls to GetFontBaked().
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
ImDrawListSharedData DrawListSharedData;
ImGuiID WithinEndChildID; // Set within EndChild()
@@ -3390,8 +3389,8 @@ namespace ImGui
IMGUI_API void UnregisterFontAtlas(ImFontAtlas* atlas);
IMGUI_API void SetCurrentFont(ImFont* font, float font_size_before_scaling, float font_size_after_scaling);
IMGUI_API void UpdateCurrentFontSize(float restore_font_size_after_scaling);
IMGUI_API void SetFontRasterizerDensity(float rasterizer_density);
inline float GetFontRasterizerDensity() { return GImGui->FontRasterizerDensity; }
IMGUI_API void SetPixelDensity(float pixel_density); // was SetFontRasterizerDensity()
inline float GetPixelDensity() { return GImGui->CurrentPixelDensity; }
inline float GetRoundedFontSize(float size) { return IM_ROUND(size); }
IMGUI_API ImFont* GetDefaultFont();
IMGUI_API void PushPasswordFont();