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