From 59014d15e7a279e19be6ef05d8788dc84ab08aa7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 28 Jul 2026 11:24:48 +0200 Subject: [PATCH] DrawList: consistently support scope flags (ImDrawFlags::Flags) + primitive flags. ImDrawFlags_AAEnds and ImDrawFlags_StrokeLegacy ok. (the most important ones). ImDrawFlags_UseTexForRoundCorners ok. ImDrawFlags_AAFill, ImDrawFlags_AAStrokes: for primitives: only for selected ones taking flags params. Haven't added the flag to all functions because it feels like a fringe use case. ImDrawFlags_TextNoPixelSnap supported in RenderText(), per-prim (9417) --- docs/CHANGELOG.txt | 1 + imgui.h | 2 +- imgui_draw.cpp | 33 +++++++++++++++++++++++---------- imgui_internal.h | 1 - 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b3b8960d6..11f6cd704 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -151,6 +151,7 @@ HOW TO UPDATE? Unifying them allows easily using them for both per-primitives and scope alterations. - (Breaking) Enabling ImFontAtlasFlags_NoBakedLines in the font atlas will disable support for anti-aliased lines. +- `ImDrawFlags_TextNoPixelSnap` may be passed to low-level RenderText() primitive. (#9417) - Tweaked line rendering in various locations to avoid blurryness: - Windows: title-bar and menu-bar border (when thickness>1.0f). - Tables: borders (when thickness>1.0f). diff --git a/imgui.h b/imgui.h index 7997e3b26..a6460850e 100644 --- a/imgui.h +++ b/imgui.h @@ -3489,7 +3489,7 @@ struct ImDrawList ImVector CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback. ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those ImVector VtxBuffer; // Vertex buffer. - ImDrawFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive. + ImDrawFlags Flags; // Current flags for drawing primitives. You may poke into these to adjust anti-aliasing settings per-primitive. Will be exposed as PushDrawFlags(). // [Internal, used while building lists] unsigned int _VtxCurrentIdx; // [Internal] generally == VtxBuffer.Size unless we are past 64K vertices, in which case this gets reset to 0. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index fa8b25c99..926c3220e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -970,7 +970,8 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 ImVec4 tex_uvs; float fringe; - if (Flags & ImDrawFlags_AALines) + flags |= Flags; + if (flags & ImDrawFlags_AALines) { _SelectFringeTexture(screen_thickness, &tex_uvs, &fringe); } @@ -1312,7 +1313,8 @@ void ImDrawList::AddPolylineLegacy(const ImVec2* points, const int points_count, // Read more details near AddRect() + see "API BREAKING CHANGES" section for 1.82, 1.90 and 1.92.8. IM_ASSERT_USER_ERROR_RET((flags & ImDrawFlags_InvalidMask_) == 0, "Incorrect parameter. Did you swap 'thickness' and 'flags'?"); - if (Flags & ImDrawFlags_AALines) + flags |= Flags; + if (flags & ImDrawFlags_AALines) { // Anti-aliased stroke const float AA_SIZE = _FringeScale; @@ -1326,7 +1328,7 @@ void ImDrawList::AddPolylineLegacy(const ImVec2* points, const int points_count, // Do we want to draw this line using a texture? // - For now, only draw integer-width lines using textures to avoid issues with the way scaling occurs, could be improved. // - If AA_SIZE is not 1.0f we cannot use the texture path. - const bool use_texture = (Flags & ImDrawFlags_UseTexForStrokeLegacy) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f) && (AA_SIZE == 1.0f); + const bool use_texture = (flags & ImDrawFlags_UseTexForStrokeLegacy) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f) && (AA_SIZE == 1.0f); // We should never hit this, because NewFrame() doesn't set ImDrawFlags_UseTexForStrokeLegacy unless ImFontAtlasFlags_NoBakedLines is off IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->OwnerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)); @@ -1572,7 +1574,8 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun }*/ const ImVec2 uv = _Data->TexUvWhitePixel; - if (Flags & ImDrawFlags_AAFill) + flags |= Flags; + if (flags & ImDrawFlags_AAFill) { const float half_aa = _FringeScale * 0.5f; ImU32 col_trans = col & ~IM_COL32_A_MASK; @@ -2179,7 +2182,7 @@ ImDrawFlags ImDrawList::_GetStrokePos(ImDrawFlags flags, ImDrawFlags default_str { if (flags & ImDrawFlags_StrokeMask_) return (flags & ImDrawFlags_StrokeMask_); - return _Data->OverrideStrokePos ? _Data->OverrideStrokePos : default_stroke_pos; + return default_stroke_pos; } IM_MSVC_RUNTIME_CHECKS_RESTORE @@ -2207,7 +2210,8 @@ void ImDrawList::_AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float t ImVec4 tex_uvs; float fringe; - if (Flags & ImDrawFlags_AALines) + flags |= Flags; + if (flags & ImDrawFlags_AALines) { _SelectFringeTexture(screen_thickness, &tex_uvs, &fringe); } @@ -2345,6 +2349,7 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th if ((col & IM_COL32_A_MASK) == 0) return; + flags |= Flags; ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeCenter); if (g_LEGACY_STROKES || stroke_pos == ImDrawFlags_StrokeLegacy) { @@ -2360,6 +2365,7 @@ void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float th if ((col & IM_COL32_A_MASK) == 0) return; + flags |= Flags; ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (g_LEGACY_STROKES || stroke_pos == ImDrawFlags_StrokeLegacy) { @@ -2405,6 +2411,7 @@ void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float th if ((col & IM_COL32_A_MASK) == 0) return; + flags |= Flags; ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (g_LEGACY_STROKES || stroke_pos == ImDrawFlags_StrokeLegacy) { @@ -2581,7 +2588,8 @@ void ImDrawList::_AddRectTinyRounding(const ImVec2& p_min, const ImVec2& p_max, ImVec4 tex_uvs; float fringe; - if (Flags & ImDrawFlags_AALines) + flags |= Flags; + if (flags & ImDrawFlags_AALines) { _SelectFringeTexture(screen_thickness, &tex_uvs, &fringe); } @@ -2715,6 +2723,7 @@ void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, fl if ((col & IM_COL32_A_MASK) == 0) return; + flags |= Flags; ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (g_LEGACY_STROKES || stroke_pos == ImDrawFlags_StrokeLegacy) IM_UNLIKELY @@ -2805,7 +2814,7 @@ void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, fl return; } // Textured corners are baked with AA, do not use them if no-AA is requested. - const bool allow_tex_corners = (Flags & (ImDrawFlags_AALines | ImDrawFlags_UseTexForRoundCorners)) == (ImDrawFlags_AALines | ImDrawFlags_UseTexForRoundCorners); + const bool allow_tex_corners = (flags & (ImDrawFlags_AALines | ImDrawFlags_UseTexForRoundCorners)) == (ImDrawFlags_AALines | ImDrawFlags_UseTexForRoundCorners); if (allow_tex_corners && s_thickness < IM_DRAWLIST_TEX_CORNERS_THICKNESS_MAX && s_rounding <= IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX) { // Pixel aligned rect with round corners rendered using baked textures. @@ -2903,6 +2912,7 @@ void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 c float width = p_max.x - p_min.x; float height = p_max.y - p_min.y; const float min_dim = ImMin(width, height); + flags |= Flags; // The rect is smaller than pixel in one dimension. if (min_dim < _FringeScale) IM_UNLIKELY @@ -2951,7 +2961,7 @@ void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 c return; } // Textured corners are baked with AA, do not use them if no-AA is requested. - const bool allow_tex_corners = (Flags & (ImDrawFlags_AAFill | ImDrawFlags_UseTexForRoundCorners)) == (ImDrawFlags_AAFill | ImDrawFlags_UseTexForRoundCorners); + const bool allow_tex_corners = (flags & (ImDrawFlags_AAFill | ImDrawFlags_UseTexForRoundCorners)) == (ImDrawFlags_AAFill | ImDrawFlags_UseTexForRoundCorners); if (allow_tex_corners && s_rounding <= IM_DRAWLIST_TEX_CORNERS_ROUNDING_MAX) { IM_ASSERT_PARANOID(!(_Data->Font->OwnerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners)); @@ -3039,6 +3049,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu if ((col & IM_COL32_A_MASK) == 0) return; + flags |= Flags; ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (g_LEGACY_STROKES || stroke_pos == ImDrawFlags_StrokeLegacy) IM_UNLIKELY { @@ -3123,6 +3134,7 @@ void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_ if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) return; + flags |= Flags; ImDrawFlags stroke_pos = _GetStrokePos(flags, ImDrawFlags_StrokeInside); if (g_LEGACY_STROKES || stroke_pos == ImDrawFlags_StrokeLegacy) IM_UNLIKELY { @@ -7684,7 +7696,8 @@ begin: float y = pos.y; if (y > clip_rect.w) return; - if ((draw_list->Flags & ImDrawFlags_TextNoPixelSnap) == 0) + flags |= draw_list->Flags; + if ((flags & ImDrawFlags_TextNoPixelSnap) == 0) { x = IM_TRUNC(x); y = IM_TRUNC(y); diff --git a/imgui_internal.h b/imgui_internal.h index 6bc659f82..20c44af6a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -951,7 +951,6 @@ 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 ImDrawFlags InitialDrawFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)