git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commita8e18dbd5514b26f73410185af6b95e8fbe8a9a6
parent6776d9f460
authorLucas Galante <[email protected]>
date2026-07-24 12:59
fix: section carve's top-right corner renders round

The carve union put the top wall (top-run piece) and the right wall
(body piece) in different pieces; each faded out approaching the shared
seam, so the top-right corner rendered square no matter the radius. Re-
split the body: one piece owns the whole right run — top wall from the
throat, top-right arc, right wall, bottom-right arc — and a left piece
carries the left wall and bottom-left arc, the two bottom runs
crossfading under the seam. Same piece count as before.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/widget/container/parameters_bg.rs | 40 +++++++++++++++--------------------
 1 file changed, 17 insertions(+), 23 deletions(-)

diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index e22bf6e..eb76940 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -1035,6 +1035,18 @@ impl ParametersBg {
                 // notched the walls there; found the hard way).
                 let throat_r = tx + tw;
                 let rho = SECTION_FILLET_R;
+                // Right of the throat, ONE piece owns the whole right run —
+                // top wall, top-right arc, right wall, bottom-right arc — so
+                // both right corners are real turns. (The old top-run +
+                // full-body split put the top wall and the right wall in
+                // different pieces; each faded out at the seam and the
+                // top-right corner rendered square.) A left piece carries the
+                // left wall and the bottom-left arc; the two bottom runs
+                // crossfade under the seam at the right piece's left edge.
+                let body_lr = |x_run: f32, out: &mut Vec<_>| {
+                    out.push((x_run, cy, cx + cw - x_run, ch, (0.0, r, r, 0.0), depth, false, (true, true, true, false)));
+                    out.push((cx, cy, x_run + depth - cx, ch, (0.0, 0.0, 0.0, r), depth, false, (false, false, true, true)));
+                };
                 if cx + cw > throat_r + 2.0 * rho {
                     // Filleted throat ([`Self::section_fillets`]): the tab's
                     // right wall must END at the fillet's vertical tangent
@@ -1044,35 +1056,17 @@ impl ParametersBg {
                     // fillet span down to the body's own fade-in.
                     out.push((tx, ty, tw, (cy - rho) - ty + depth, (r, r, 0.0, 0.0), depth, false, (true, true, false, true)));
                     out.push((tx, cy - rho, tw, rho + depth, (0.0, 0.0, 0.0, 0.0), depth, false, (false, false, false, true)));
-                    out.push((
-                        throat_r + rho - depth,
-                        cy,
-                        cx + cw - throat_r - rho + depth,
-                        ch,
-                        (0.0, r, 0.0, 0.0),
-                        depth,
-                        false,
-                        (true, false, false, false),
-                    ));
+                    body_lr(throat_r + rho - depth, &mut out);
                 } else {
                     // Too narrow for the fillet: the plain square throat.
                     out.push((tx, ty, tw, th + depth, (r, r, 0.0, 0.0), depth, false, (true, true, false, true)));
                     if cx + cw > throat_r + 0.5 {
-                        out.push((
-                            throat_r - depth,
-                            cy,
-                            cx + cw - throat_r + depth,
-                            ch,
-                            (0.0, r, 0.0, 0.0),
-                            depth,
-                            false,
-                            (true, false, false, false),
-                        ));
+                        body_lr(throat_r - depth, &mut out);
+                    } else {
+                        // The tab spans the body: no top wall at all.
+                        out.push((cx, cy, cw, ch, (0.0, 0.0, r, r), depth, false, (false, true, true, true)));
                     }
                 }
-                // Body: top open — its top wall comes from the segment beside
-                // the tab's throat.
-                out.push((cx, cy, cw, ch, (0.0, 0.0, r, r), depth, false, (false, true, true, true)));
             } else {
                 let depth = crate::layout::bevel_width().min(th * 0.2).min(CHANNEL);
                 out.push((tx, ty, tw, th, r4(SECTION_R), depth, false, all));