1use crate::{Color32, CornerRadius, MarginF32, Rect, RectShape, Vec2};
2
3#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
9#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
10pub struct Shadow {
11 pub offset: [i8; 2],
16
17 pub blur: u8,
21
22 pub spread: u8,
24
25 pub color: Color32,
27}
28
29#[test]
30fn shadow_size() {
31 assert_eq!(
32 std::mem::size_of::<Shadow>(),
33 8,
34 "Shadow changed size! If it shrank - good! Update this test. If it grew - bad! Try to find a way to avoid it."
35 );
36}
37
38impl Shadow {
39 pub const NONE: Self = Self {
41 offset: [0, 0],
42 blur: 0,
43 spread: 0,
44 color: Color32::TRANSPARENT,
45 };
46
47 pub fn as_shape(&self, rect: Rect, corner_radius: impl Into<CornerRadius>) -> RectShape {
49 let Self {
52 offset,
53 blur,
54 spread,
55 color,
56 } = *self;
57 let [offset_x, offset_y] = offset;
58
59 let rect = rect
60 .translate(Vec2::new(offset_x as _, offset_y as _))
61 .expand(spread as _);
62 let corner_radius = corner_radius.into() + CornerRadius::from(spread);
63
64 RectShape::filled(rect, corner_radius, color).with_blur_width(blur as _)
65 }
66
67 pub fn margin(&self) -> MarginF32 {
69 let Self {
70 offset,
71 blur,
72 spread,
73 color: _,
74 } = *self;
75 let spread = spread as f32;
76 let blur = blur as f32;
77 let [offset_x, offset_y] = offset;
78 MarginF32 {
79 left: spread + 0.5 * blur - offset_x as f32,
80 right: spread + 0.5 * blur + offset_x as f32,
81 top: spread + 0.5 * blur - offset_y as f32,
82 bottom: spread + 0.5 * blur + offset_y as f32,
83 }
84 }
85}