From 753cb8474d7b752414608e106a9558d1dcc67fe4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 May 2026 17:40:16 +0200 Subject: [PATCH] DrawList: added _GetStrokePos() helper indirection, made flags=0 select default at runtime. --- imgui.h | 11 ++++++----- imgui_demo.cpp | 3 ++- imgui_draw.cpp | 25 ++++++++++++++++++------- imgui_internal.h | 1 + 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/imgui.h b/imgui.h index f7a0a8b6e..a1fdb8afe 100644 --- a/imgui.h +++ b/imgui.h @@ -3445,11 +3445,11 @@ enum ImDrawFlags_ //ImDrawFlags_Closed = 1, // Prior to 1.92.8 (May 2026), ImDrawFlags_Closed was guaranteed to be == 1<<0 == 1 for legacy compatibility reason. Hardcoded use of 1 or true should be replaced. // Stroke position relative to the shape outline - ImDrawFlags_StrokeInside = 0 << 16, // Draw stroke inside of the shape outline (Default) - ImDrawFlags_StrokeCenter = 1 << 16, // Draw stroke at the center of the shape outline - ImDrawFlags_StrokeCenterPixelAligned = 2 << 16, // Draw stroke at the center of the shape outline, so that half thickness (rounded down) will be outside, and rest inside the shape outline. - ImDrawFlags_StrokeOutside = 3 << 16, // Draw stroke outside of the shape outline - ImDrawFlags_StrokeLegacy = 4 << 16, // Use legacy position + ImDrawFlags_StrokeInside = 1 << 16, // Draw stroke inside of the shape outline (Default) + ImDrawFlags_StrokeCenter = 2 << 16, // Draw stroke at the center of the shape outline + ImDrawFlags_StrokeCenterPixelAligned = 3 << 16, // Draw stroke at the center of the shape outline, so that half thickness (rounded down) will be outside, and rest inside the shape outline. + ImDrawFlags_StrokeOutside = 4 << 16, // Draw stroke outside of the shape outline + ImDrawFlags_StrokeLegacy = 5 << 16, // Use legacy position ImDrawFlags_StrokeMask_ = 0x07 << 16, ImDrawFlags_InvalidMask_ = ~0x7FFFFFF0, // == 0x8000000F, @@ -3640,6 +3640,7 @@ struct ImDrawList IMGUI_API void _OnChangedTexture(); IMGUI_API void _OnChangedVtxOffset(); IMGUI_API void _SetTexture(ImTextureRef tex_ref); + IMGUI_API ImDrawFlags _GetStrokePos(ImDrawFlags flags, ImDrawFlags default_stroke_pos); IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const; IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step); IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f4e833cda..fb1376bec 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -10429,9 +10429,10 @@ static void ShowExampleAppCustomRendering(bool* p_open) curve_segments_override |= ImGui::SliderInt("Curves segments override", &curve_segments_override_v, 3, 40); ImGui::ColorEdit4("Color", &colf.x); - static ImDrawFlags flags = 0; + static ImDrawFlags flags = ImDrawFlags_None; ImGui::AlignTextToFramePadding(); ImGui::Text("Stroke:"); + ImGui::SameLine(); ImGui::RadioButton("Default", &flags, ImDrawFlags_None); ImGui::SameLine(); ImGui::RadioButton("Inside", &flags, ImDrawFlags_StrokeInside); ImGui::SameLine(); ImGui::RadioButton("Center", &flags, ImDrawFlags_StrokeCenter); ImGui::SameLine(); ImGui::RadioButton("CenterPixelAligned", &flags, ImDrawFlags_StrokeCenterPixelAligned); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 29007d1ad..c51536db9 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1512,11 +1512,22 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDr extern bool g_LEGACY_STROKES; +// We intently don't turn g_LEGACY_STROKES into ImDrawFlags_StrokeLegacy here. +// The earlier should use verbatim legacy code but will be removed before release once we confirm that both matches. +ImDrawFlags ImDrawList::_GetStrokePos(ImDrawFlags flags, ImDrawFlags default_stroke_pos) +{ + if (flags & ImDrawFlags_StrokeMask_) + return (flags & ImDrawFlags_StrokeMask_); + return _Data->OverrideStrokePos ? _Data->OverrideStrokePos : default_stroke_pos; +} + void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness, ImDrawFlags flags) { if ((col & IM_COL32_A_MASK) == 0) return; - if (g_LEGACY_STROKES || (flags & ImDrawFlags_StrokeMask_) == ImDrawFlags_StrokeLegacy) + + ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeCenter); // WIP: only Legacy is used. + if (g_LEGACY_STROKES || stroke_pos == ImDrawFlags_StrokeLegacy) { const ImVec2 points[2] = { ImVec2(p1.x + 0.5f, p1.y + 0.5f), ImVec2(p2.x + 0.5f, p2.y + 0.5f) }; AddPolyline(points, 2, col, thickness); @@ -1539,7 +1550,7 @@ void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float th return; } - ImDrawFlags stroke_pos = (flags & ImDrawFlags_StrokeMask_); + ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (stroke_pos == ImDrawFlags_StrokeCenter) y -= thickness * 0.5f; else if (stroke_pos == ImDrawFlags_StrokeCenterPixelAligned) @@ -1570,7 +1581,7 @@ void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float th return; } - ImDrawFlags stroke_pos = (flags & ImDrawFlags_StrokeMask_); + ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (stroke_pos == ImDrawFlags_StrokeCenter) x -= thickness * 0.5f; else if (stroke_pos == ImDrawFlags_StrokeCenterPixelAligned) @@ -1736,7 +1747,7 @@ void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, fl } const bool is_truncated = _FringeScaleIsInteger && ImIsTruncated4(p_min.x, p_min.y, p_max.x, p_max.y) && ImIsTruncated4(rounding, thickness, 0.0f, 0.0f); - ImDrawFlags stroke_pos = (flags & ImDrawFlags_StrokeMask_); + ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if ((stroke_pos == ImDrawFlags_StrokeInside || stroke_pos == ImDrawFlags_StrokeOutside || stroke_pos == ImDrawFlags_StrokeCenterPixelAligned) && is_truncated) { if ((flags & ImDrawFlags_RoundCornersMask_) == 0) @@ -2011,7 +2022,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu } else { - const ImDrawFlags stroke_pos = (flags & ImDrawFlags_StrokeMask_); + ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (stroke_pos == ImDrawFlags_StrokeInside) radius -= thickness * 0.5f; else if (stroke_pos == ImDrawFlags_StrokeCenterPixelAligned) @@ -2077,7 +2088,7 @@ void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_ } else { - const ImDrawFlags stroke_pos = (flags & ImDrawFlags_StrokeMask_); + ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (stroke_pos == ImDrawFlags_StrokeInside) radius -= thickness * 0.5f; else if (stroke_pos == ImDrawFlags_StrokeCenterPixelAligned) @@ -2120,7 +2131,7 @@ void ImDrawList::AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 co else { r = radius; - ImDrawFlags stroke_pos = (flags & ImDrawFlags_StrokeMask_); + ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (stroke_pos == ImDrawFlags_StrokeInside) r -= ImVec2(thickness * 0.5f, thickness * 0.5f); else if (stroke_pos == ImDrawFlags_StrokeCenterPixelAligned) diff --git a/imgui_internal.h b/imgui_internal.h index f89873135..ba1d3dccf 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -925,6 +925,7 @@ struct IMGUI_API ImDrawListSharedData ImFont* Font; // Current font (used for simplified AddText overload) float FontSize; // Current font size (used for for simplified AddText overload) float FontScale; // Current font scale (== FontSize / Font->FontSize) + ImDrawFlags OverrideStrokePos; // Override default StrokePos when not specified by an individual primitive. == 0 or ImDrawFlags_StrokeLegacy only. float CurveTessellationMaxError; // Tessellation tolerance when using PathBezierCurveTo() float CircleTessellationMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)