cosmic/surface/
corner_radius.rs1use iced::Rectangle;
2use iced_runtime::platform_specific::wayland::CornerRadius;
3
4#[must_use]
5pub fn rounded_rect_strips(rect: Rectangle<f32>, radius: CornerRadius) -> Vec<Rectangle<f32>> {
6 let mut out = Vec::new();
7
8 let w = rect.width.max(0.0);
9 let h = rect.height.max(0.0);
10
11 if w <= 0.0 || h <= 0.0 {
12 return out;
13 }
14
15 let tl = radius.top_left as i32;
16 let tr = radius.top_right as i32;
17 let bl = radius.bottom_left as i32;
18 let br = radius.bottom_right as i32;
19
20 let max_top = tl.max(tr);
21 let max_bottom = bl.max(br);
22
23 let center_y = rect.y + max_top as f32;
24 let center_h = (h as i32 - max_top - max_bottom).max(0) as f32;
25
26 if center_h > 0.0 {
27 out.push(Rectangle {
28 x: rect.x,
29 y: center_y,
30 width: w,
31 height: center_h,
32 });
33 }
34
35 for y in 0..max_top {
36 let left = if y < tl { circle_inset(tl, y) } else { 0 };
37
38 let right = if y < tr { circle_inset(tr, y) } else { 0 };
39
40 let strip_x = rect.x + left as f32;
41 let strip_w = (w as i32 - left - right).max(0) as f32;
42
43 if strip_w > 0.0 {
44 out.push(Rectangle {
45 x: strip_x,
46 y: rect.y + y as f32,
47 width: strip_w,
48 height: if h > 1. { 2. } else { 1. },
49 });
50 }
51 }
52
53 for y in 0..max_bottom {
54 let cy = max_bottom - 1 - y;
55 let left = if cy < bl { circle_inset(bl, cy) } else { 0 };
56
57 let right = if cy < br { circle_inset(br, cy) } else { 0 };
58
59 let strip_x = rect.x + left as f32;
60 let strip_w = (w as i32 - left - right).max(0) as f32;
61
62 if strip_w > 0.0 {
63 out.push(Rectangle {
64 x: strip_x,
65 y: rect.y + h - max_bottom as f32 + y as f32 - if h > 1. { 1. } else { 0. },
66 width: strip_w,
67 height: if h > 1. { 2. } else { 1. },
68 });
69 }
70 }
71
72 out
73}
74
75fn circle_inset(radius: i32, y: i32) -> i32 {
76 if radius <= 0 {
77 return 0;
78 }
79
80 let fy = y as f32 + 0.5;
81 let r = radius as f32;
82
83 let x = r - (r * r - (r - fy) * (r - fy)).sqrt();
84
85 x.floor() as i32
86}