orbtk_utils/
gradients.rs

1use crate::{Angle, Color, OnLinePos, OnPlanePos, Point, RelativeDir};
2
3/// Describes a position on a colorful gradient.
4#[derive(Copy, Clone, Debug, Default, PartialEq)]
5pub struct GradientStop {
6    pub pos: Option<OnLinePos>,
7    pub color: Color,
8}
9
10impl GradientStop {
11    /// Creates a new stop mark.
12    pub fn new(pos: Option<OnLinePos>, color: Color) -> GradientStop {
13        GradientStop { pos, color }
14    }
15}
16
17impl From<(OnLinePos, Color)> for GradientStop {
18    fn from(d: (OnLinePos, Color)) -> Self {
19        Self {
20            pos: Some(d.0),
21            color: d.1,
22        }
23    }
24}
25
26impl From<(f64, Color)> for GradientStop {
27    fn from(d: (f64, Color)) -> Self {
28        Self {
29            pos: Some(OnLinePos::from_unit_percent(d.0)),
30            color: d.1,
31        }
32    }
33}
34
35impl From<Color> for GradientStop {
36    fn from(color: Color) -> Self {
37        Self { pos: None, color }
38    }
39}
40
41/// Describes the coordinates of a colorful linear gradient.
42#[derive(Copy, Clone, PartialEq, Debug)]
43pub enum LinearGradientCoords {
44    /// Defines the linear gradient by point A to point B.
45    Ends { start: Point, end: Point },
46    /// Defines the linear gradient using an angle and a displacement from the center of the target figure.
47    Angle {
48        angle: Angle,
49        // Defines a displacement from the center of the target shape.
50        displacement: OnPlanePos,
51    },
52    // Defines a gradient as one that crosses the figure in a given direction.
53    Direction {
54        direction: RelativeDir,
55        displacement: OnPlanePos,
56    },
57}
58
59impl LinearGradientCoords {
60    /// Creates a `LinearGradientCoords` from its ends.
61    pub fn from_ends(start: impl Into<Point>, end: impl Into<Point>) -> LinearGradientCoords {
62        LinearGradientCoords::Ends {
63            start: start.into(),
64            end: end.into(),
65        }
66    }
67
68    /// Creates a `LinearGradientCoords` from its angle.
69    pub fn from_angle(angle: Angle) -> LinearGradientCoords {
70        LinearGradientCoords::Angle {
71            angle,
72            displacement: OnPlanePos::default(),
73        }
74    }
75
76    /// Sets the displacement if `self` is defined by its angle, otherwise, this does nothing.
77    pub fn with_displacement(&mut self, displacement: impl Into<OnPlanePos>) -> Self {
78        if let LinearGradientCoords::Angle {
79            angle: _,
80            displacement: disp,
81        } = self
82        {
83            *disp = displacement.into();
84        }
85        *self
86    }
87}
88
89impl Default for LinearGradientCoords {
90    fn default() -> LinearGradientCoords {
91        LinearGradientCoords::Direction {
92            direction: RelativeDir::Top,
93            displacement: OnPlanePos::default(),
94        }
95    }
96}
97
98/// Describes a colorful gradient.
99#[derive(Clone, PartialEq, Debug)]
100pub struct Gradient {
101    pub kind: GradientKind,
102    pub stops: Vec<GradientStop>,
103    pub repeat: bool,
104}
105
106impl Default for Gradient {
107    fn default() -> Self {
108        Self {
109            kind: GradientKind::Linear(LinearGradientCoords::default()),
110            stops: vec![
111                GradientStop {
112                    pos: None,
113                    color: Color::rgb(0, 0, 0),
114                },
115                GradientStop {
116                    pos: None,
117                    color: Color::rgb(255, 255, 255),
118                },
119            ],
120            repeat: false,
121        }
122    }
123}
124
125/// Describes the kind of a gradient.
126#[derive(Copy, Clone, PartialEq, Debug)]
127pub enum GradientKind {
128    Linear(LinearGradientCoords),
129    // Radial(RadialGradient),
130}
131
132impl Default for GradientKind {
133    fn default() -> GradientKind {
134        GradientKind::Linear(LinearGradientCoords::default())
135    }
136}