epaint/
shadow.rs

1use super::{Color32, Margin, Rect, RectShape, Rounding, Vec2};
2
3/// The color and fuzziness of a fuzzy shape.
4///
5/// Can be used for a rectangular shadow with a soft penumbra.
6///
7/// Very similar to a box-shadow in CSS.
8#[derive(Clone, Copy, Debug, Default, PartialEq)]
9#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
10pub struct Shadow {
11    /// Move the shadow by this much.
12    ///
13    /// For instance, a value of `[1.0, 2.0]` will move the shadow 1 point to the right and 2 points down,
14    /// causing a drop-shadow effect.
15    pub offset: Vec2,
16
17    /// The width of the blur, i.e. the width of the fuzzy penumbra.
18    ///
19    /// A value of 0.0 means a sharp shadow.
20    pub blur: f32,
21
22    /// Expand the shadow in all directions by this much.
23    pub spread: f32,
24
25    /// Color of the opaque center of the shadow.
26    pub color: Color32,
27}
28
29impl Shadow {
30    /// No shadow at all.
31    pub const NONE: Self = Self {
32        offset: Vec2::ZERO,
33        blur: 0.0,
34        spread: 0.0,
35        color: Color32::TRANSPARENT,
36    };
37
38    /// The argument is the rectangle of the shadow caster.
39    pub fn as_shape(&self, rect: Rect, rounding: impl Into<Rounding>) -> RectShape {
40        // tessellator.clip_rect = clip_rect; // TODO(emilk): culling
41
42        let Self {
43            offset,
44            blur,
45            spread,
46            color,
47        } = *self;
48
49        let rect = rect.translate(offset).expand(spread);
50        let rounding = rounding.into() + Rounding::same(spread.abs());
51
52        RectShape::filled(rect, rounding, color).with_blur_width(blur)
53    }
54
55    /// How much larger than the parent rect are we in each direction?
56    pub fn margin(&self) -> Margin {
57        let Self {
58            offset,
59            blur,
60            spread,
61            color: _,
62        } = *self;
63        Margin {
64            left: spread + 0.5 * blur - offset.x,
65            right: spread + 0.5 * blur + offset.x,
66            top: spread + 0.5 * blur - offset.y,
67            bottom: spread + 0.5 * blur + offset.y,
68        }
69    }
70}