firefly_rust/graphics/
types.rs

1/// The RGB value of a color in the palette.
2#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
3pub struct RGB {
4    /// Red component.
5    pub r: u8,
6    /// Green component.
7    pub g: u8,
8    /// Blue component.
9    pub b: u8,
10}
11
12/// Style of a shape.
13#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
14pub struct Style {
15    /// The color to use to fill the shape.
16    pub fill_color: Color,
17
18    /// The color to use for the shape stroke.
19    pub stroke_color: Color,
20
21    /// The width of the shape stroke.
22    ///
23    /// If zero, a solid shape without a stroke will be drawn.
24    pub stroke_width: i32,
25}
26
27impl Default for Style {
28    fn default() -> Self {
29        Self {
30            fill_color: Color::None,
31            stroke_color: Color::None,
32            stroke_width: 1,
33        }
34    }
35}
36
37impl Style {
38    /// Create a shape style filled with a color and without a stroke.
39    #[must_use]
40    pub const fn solid(c: Color) -> Self {
41        Self {
42            fill_color: c,
43            stroke_color: Color::None,
44            stroke_width: 0,
45        }
46    }
47
48    /// Create a shape style with a stroke and no fill color (transparent body).
49    #[must_use]
50    pub const fn outlined(c: Color, w: i32) -> Self {
51        Self {
52            fill_color: Color::None,
53            stroke_color: c,
54            stroke_width: w,
55        }
56    }
57
58    /// Convert the style to a line style.
59    ///
60    /// [`LineStyle`] is the same as [Style] except it doesn't have a fill color.
61    #[must_use]
62    pub const fn as_line_style(&self) -> LineStyle {
63        LineStyle {
64            color: self.stroke_color,
65            width: self.stroke_width,
66        }
67    }
68}
69
70impl From<LineStyle> for Style {
71    fn from(value: LineStyle) -> Self {
72        Self {
73            fill_color: Color::None,
74            stroke_color: value.color,
75            stroke_width: value.width,
76        }
77    }
78}
79
80/// The same as [Style] but without a fill color (only stroke color and width).
81#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
82pub struct LineStyle {
83    /// The line stroke color.
84    pub color: Color,
85    /// The line stroke width.
86    pub width: i32,
87}
88
89impl LineStyle {
90    /// Create a new style for a line.
91    #[must_use]
92    pub const fn new(c: Color, w: i32) -> Self {
93        Self { color: c, width: w }
94    }
95}
96
97impl From<Style> for LineStyle {
98    fn from(value: Style) -> Self {
99        Self {
100            color: value.stroke_color,
101            width: value.stroke_width,
102        }
103    }
104}
105
106/// A pointer to a color in the color palette.
107#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
108pub enum Color {
109    /// No color (100% transparency).
110    None,
111    /// Black color: #1A1C2C.
112    Black,
113    /// Purple color: #5D275D.
114    Purple,
115    /// Red color: #B13E53.
116    Red,
117    /// Orange color: #EF7D57.
118    Orange,
119    /// Yellow color: #FFCD75.
120    Yellow,
121    /// Light green color: #A7F070.
122    LightGreen,
123    /// Green color: #38B764.
124    Green,
125    /// Dark green color: #257179.
126    DarkGreen,
127    /// Dark blue color: #29366F.
128    DarkBlue,
129    /// Blue color: #3B5DC9.
130    Blue,
131    /// Light blue color: #41A6F6.
132    LightBlue,
133    /// Cyan color: #73EFF7.
134    Cyan,
135    /// White color: #F4F4F4.
136    White,
137    /// Light gray color: #94B0C2.
138    LightGray,
139    /// Gray color: #566C86.
140    Gray,
141    /// Dark gray color: #333C57.
142    DarkGray,
143}
144
145impl Default for Color {
146    fn default() -> Self {
147        Self::None
148    }
149}
150
151impl TryFrom<usize> for Color {
152    type Error = ();
153
154    fn try_from(value: usize) -> Result<Self, Self::Error> {
155        match value {
156            0 => Ok(Color::None),
157            1 => Ok(Color::Black),
158            2 => Ok(Color::Purple),
159            3 => Ok(Color::Red),
160            4 => Ok(Color::Orange),
161            5 => Ok(Color::Yellow),
162            6 => Ok(Color::LightGreen),
163            7 => Ok(Color::Green),
164            8 => Ok(Color::DarkGreen),
165            9 => Ok(Color::DarkBlue),
166            10 => Ok(Color::Blue),
167            11 => Ok(Color::LightBlue),
168            12 => Ok(Color::Cyan),
169            13 => Ok(Color::White),
170            14 => Ok(Color::LightGray),
171            15 => Ok(Color::Gray),
172            16 => Ok(Color::DarkGray),
173            _ => Err(()),
174        }
175    }
176}
177
178impl From<Color> for i32 {
179    fn from(value: Color) -> Self {
180        match value {
181            Color::None => 0,
182            Color::Black => 1,
183            Color::Purple => 2,
184            Color::Red => 3,
185            Color::Orange => 4,
186            Color::Yellow => 5,
187            Color::LightGreen => 6,
188            Color::Green => 7,
189            Color::DarkGreen => 8,
190            Color::DarkBlue => 9,
191            Color::Blue => 10,
192            Color::LightBlue => 11,
193            Color::Cyan => 12,
194            Color::White => 13,
195            Color::LightGray => 14,
196            Color::Gray => 15,
197            Color::DarkGray => 16,
198        }
199    }
200}
201
202impl From<Option<Color>> for Color {
203    fn from(value: Option<Color>) -> Self {
204        value.unwrap_or(Color::None)
205    }
206}