From bb0145c566724340e65b0ec1617add643a82dd98 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Tue, 30 Jun 2026 11:06:41 -0400 Subject: [PATCH] chore: add the rounded rectangle strip helper --- src/surface/corner_radius.rs | 86 ++++++++++++++++++++++++++++++++++++ src/surface/mod.rs | 2 + src/widget/button/widget.rs | 2 +- 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/surface/corner_radius.rs diff --git a/src/surface/corner_radius.rs b/src/surface/corner_radius.rs new file mode 100644 index 00000000..1eda578d --- /dev/null +++ b/src/surface/corner_radius.rs @@ -0,0 +1,86 @@ +use iced::Rectangle; +use iced_runtime::platform_specific::wayland::CornerRadius; + +#[must_use] +pub fn rounded_rect_strips(rect: Rectangle, radius: CornerRadius) -> Vec> { + let mut out = Vec::new(); + + let w = rect.width.max(0.0); + let h = rect.height.max(0.0); + + if w <= 0.0 || h <= 0.0 { + return out; + } + + let tl = radius.top_left as i32; + let tr = radius.top_right as i32; + let bl = radius.bottom_left as i32; + let br = radius.bottom_right as i32; + + let max_top = tl.max(tr); + let max_bottom = bl.max(br); + + let center_y = rect.y + max_top as f32; + let center_h = (h as i32 - max_top - max_bottom).max(0) as f32; + + if center_h > 0.0 { + out.push(Rectangle { + x: rect.x, + y: center_y, + width: w, + height: center_h, + }); + } + + for y in 0..max_top { + let left = if y < tl { circle_inset(tl, y) } else { 0 }; + + let right = if y < tr { circle_inset(tr, y) } else { 0 }; + + let strip_x = rect.x + left as f32; + let strip_w = (w as i32 - left - right).max(0) as f32; + + if strip_w > 0.0 { + out.push(Rectangle { + x: strip_x, + y: rect.y + y as f32, + width: strip_w, + height: 1.0, + }); + } + } + + for y in 0..max_bottom { + let cy = max_bottom - 1 - y; + let left = if cy < bl { circle_inset(bl, cy) } else { 0 }; + + let right = if cy < br { circle_inset(br, cy) } else { 0 }; + + let strip_x = rect.x + left as f32; + let strip_w = (w as i32 - left - right).max(0) as f32; + + if strip_w > 0.0 { + out.push(Rectangle { + x: strip_x, + y: rect.y + h - max_bottom as f32 + y as f32, + width: strip_w, + height: 1.0, + }); + } + } + + out +} + +fn circle_inset(radius: i32, y: i32) -> i32 { + if radius <= 0 { + return 0; + } + + let fy = y as f32 + 0.5; + let r = radius as f32; + + let x = r - (r * r - (r - fy) * (r - fy)).sqrt(); + + x.floor() as i32 +} diff --git a/src/surface/mod.rs b/src/surface/mod.rs index eec81e3f..b3858b97 100644 --- a/src/surface/mod.rs +++ b/src/surface/mod.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: MPL-2.0 pub mod action; +#[cfg(all(feature = "wayland", target_os = "linux"))] +pub mod corner_radius; use iced::{Limits, Size, Task}; use std::any::Any; diff --git a/src/widget/button/widget.rs b/src/widget/button/widget.rs index 5ebfc5b2..a9d44b2b 100644 --- a/src/widget/button/widget.rs +++ b/src/widget/button/widget.rs @@ -488,7 +488,7 @@ impl<'a, Message: 'a + Clone> Widget None => { styling.border_radius = theme.cosmic().radius_0().into(); } - }; + } } let mut icon_color = styling.icon_color.unwrap_or(renderer_style.icon_color);