Skip to main content

lgui_core/core/foundation/
style.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2pub struct Color(pub u32);
3
4impl Color {
5    pub const BLACK: Self = Self(0x000000);
6    pub const WHITE: Self = Self(0xFFFFFF);
7}
8
9use std::hash::{Hash, Hasher};
10
11use super::geometry::normalized_f32_bits;
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum ImageFit {
15    Contain,
16    Cover,
17    Fill,
18}
19
20#[derive(Clone, Copy, Debug, PartialEq)]
21pub struct Stroke {
22    pub color: Color,
23    pub width: f32,
24    pub alpha: u8,
25}
26
27impl Stroke {
28    pub const fn new(color: Color, width: f32, alpha: u8) -> Self {
29        Self {
30            color,
31            width,
32            alpha,
33        }
34    }
35}
36
37impl Eq for Stroke {}
38
39impl Hash for Stroke {
40    fn hash<H: Hasher>(&self, state: &mut H) {
41        self.color.hash(state);
42        normalized_f32_bits(self.width).hash(state);
43        self.alpha.hash(state);
44    }
45}
46
47#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
48pub enum TextAlign {
49    Left,
50    Center,
51    Right,
52}
53
54#[derive(Clone, Copy, Debug, PartialEq)]
55pub struct TextStyle {
56    pub color: Color,
57    pub height: f32,
58    pub weight: i32,
59    pub tracking: f32,
60    pub align: TextAlign,
61    pub alpha: u8,
62}
63
64impl TextStyle {
65    pub const fn new(color: Color, height: f32, weight: i32) -> Self {
66        Self {
67            color,
68            height,
69            weight,
70            tracking: 0.0,
71            align: TextAlign::Left,
72            alpha: 0xFF,
73        }
74    }
75
76    pub const fn centered(mut self) -> Self {
77        self.align = TextAlign::Center;
78        self
79    }
80
81    pub const fn tracking(mut self, tracking: f32) -> Self {
82        self.tracking = tracking;
83        self
84    }
85
86    pub const fn alpha(mut self, alpha: u8) -> Self {
87        self.alpha = alpha;
88        self
89    }
90}
91
92impl Eq for TextStyle {}
93
94impl Hash for TextStyle {
95    fn hash<H: Hasher>(&self, state: &mut H) {
96        self.color.hash(state);
97        normalized_f32_bits(self.height).hash(state);
98        self.weight.hash(state);
99        normalized_f32_bits(self.tracking).hash(state);
100        self.align.hash(state);
101        self.alpha.hash(state);
102    }
103}
104
105#[derive(Clone, Copy, Debug, PartialEq)]
106pub struct VisualStyle {
107    pub fill: Option<Color>,
108    pub fill_alpha: u8,
109    pub stroke: Option<Stroke>,
110    pub radius: f32,
111}
112
113impl Eq for VisualStyle {}
114
115impl Hash for VisualStyle {
116    fn hash<H: Hasher>(&self, state: &mut H) {
117        self.fill.hash(state);
118        self.fill_alpha.hash(state);
119        self.stroke.hash(state);
120        normalized_f32_bits(self.radius).hash(state);
121    }
122}
123
124#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
125pub struct PathStyle {
126    pub fill: Option<Color>,
127    pub fill_alpha: u8,
128    pub stroke: Option<Stroke>,
129}
130
131#[derive(Clone, Copy, Debug, PartialEq, Eq)]
132pub enum UiPathCommand {
133    MoveTo(super::Point),
134    LineTo(super::Point),
135    QuadraticTo {
136        control: super::Point,
137        to: super::Point,
138    },
139    CubicTo {
140        control1: super::Point,
141        control2: super::Point,
142        to: super::Point,
143    },
144    Close,
145}
146
147#[derive(Clone, Debug, Default, PartialEq, Eq)]
148pub struct UiPath {
149    pub commands: Vec<UiPathCommand>,
150}
151
152impl UiPath {
153    pub fn new(commands: impl IntoIterator<Item = UiPathCommand>) -> Self {
154        Self {
155            commands: commands.into_iter().collect(),
156        }
157    }
158
159    pub fn commands(&self) -> &[UiPathCommand] {
160        &self.commands
161    }
162}
163
164#[derive(Clone, Copy, Debug, PartialEq)]
165pub struct VerticalGradientLayer {
166    pub color: Color,
167    pub alpha_top: f32,
168    pub alpha_bottom: f32,
169}
170
171impl VerticalGradientLayer {
172    pub const fn new(color: Color, alpha_top: f32, alpha_bottom: f32) -> Self {
173        Self {
174            color,
175            alpha_top,
176            alpha_bottom,
177        }
178    }
179}
180
181#[derive(Clone, Copy, Debug, PartialEq)]
182pub struct RadialGradientLayer {
183    pub color: Color,
184    pub alpha: f32,
185    pub center_x: f32,
186    pub center_y: f32,
187    pub radius: f32,
188}
189
190impl RadialGradientLayer {
191    pub const fn new(color: Color, alpha: f32, center_x: f32, center_y: f32, radius: f32) -> Self {
192        Self {
193            color,
194            alpha,
195            center_x,
196            center_y,
197            radius,
198        }
199    }
200}
201
202#[derive(Clone, Debug, Default, PartialEq)]
203pub struct OverlayStyle {
204    pub vertical_layers: Vec<VerticalGradientLayer>,
205    pub radial_layers: Vec<RadialGradientLayer>,
206}
207
208impl OverlayStyle {
209    pub fn new() -> Self {
210        Self::default()
211    }
212
213    pub fn vertical(mut self, layer: VerticalGradientLayer) -> Self {
214        self.vertical_layers.push(layer);
215        self
216    }
217
218    pub fn radial(mut self, layer: RadialGradientLayer) -> Self {
219        self.radial_layers.push(layer);
220        self
221    }
222}
223
224#[derive(Clone, Copy, Debug, PartialEq)]
225pub struct BackdropBlurStyle {
226    pub source: &'static str,
227    pub fit: ImageFit,
228    pub source_rect: super::UiRect,
229    pub radius: f32,
230    pub opacity: f32,
231    pub tint: Color,
232    pub tint_alpha: f32,
233}
234
235impl BackdropBlurStyle {
236    pub const fn new(source: &'static str, fit: ImageFit, source_rect: super::UiRect) -> Self {
237        Self {
238            source,
239            fit,
240            source_rect,
241            radius: 24.0,
242            opacity: 1.0,
243            tint: Color::BLACK,
244            tint_alpha: 0.0,
245        }
246    }
247
248    pub const fn radius(mut self, radius: f32) -> Self {
249        self.radius = radius;
250        self
251    }
252
253    pub const fn opacity(mut self, opacity: f32) -> Self {
254        self.opacity = opacity;
255        self
256    }
257
258    pub const fn tint(mut self, tint: Color, alpha: f32) -> Self {
259        self.tint = tint;
260        self.tint_alpha = alpha;
261        self
262    }
263}
264
265#[derive(Clone, Copy, Debug, PartialEq)]
266pub struct CustomPaintStyle {
267    pub color: Color,
268    pub intensity: f32,
269}
270
271impl CustomPaintStyle {
272    pub const fn new(color: Color, intensity: f32) -> Self {
273        Self { color, intensity }
274    }
275}
276
277#[derive(Clone, Copy, Debug, PartialEq, Eq)]
278pub struct IconStyle {
279    pub color: Color,
280    pub alpha: u8,
281}
282
283impl IconStyle {
284    pub const fn new(color: Color) -> Self {
285        Self { color, alpha: 0xFF }
286    }
287
288    pub const fn alpha(mut self, alpha: u8) -> Self {
289        self.alpha = alpha;
290        self
291    }
292}
293
294impl Default for VisualStyle {
295    fn default() -> Self {
296        Self {
297            fill: None,
298            fill_alpha: 0xFF,
299            stroke: None,
300            radius: 0.0,
301        }
302    }
303}
304
305impl Default for PathStyle {
306    fn default() -> Self {
307        Self {
308            fill: None,
309            fill_alpha: 0xFF,
310            stroke: None,
311        }
312    }
313}
314
315impl VisualStyle {
316    pub const fn filled(fill: Color) -> Self {
317        Self {
318            fill: Some(fill),
319            fill_alpha: 0xFF,
320            stroke: None,
321            radius: 0.0,
322        }
323    }
324
325    pub const fn stroked(mut self, stroke: Stroke) -> Self {
326        self.stroke = Some(stroke);
327        self
328    }
329
330    pub const fn radius(mut self, radius: f32) -> Self {
331        self.radius = radius;
332        self
333    }
334
335    pub const fn alpha(mut self, alpha: u8) -> Self {
336        self.fill_alpha = alpha;
337        self
338    }
339}
340
341impl PathStyle {
342    pub const fn filled(fill: Color) -> Self {
343        Self {
344            fill: Some(fill),
345            fill_alpha: 0xFF,
346            stroke: None,
347        }
348    }
349
350    pub const fn stroked(mut self, stroke: Stroke) -> Self {
351        self.stroke = Some(stroke);
352        self
353    }
354
355    pub const fn alpha(mut self, alpha: u8) -> Self {
356        self.fill_alpha = alpha;
357        self
358    }
359}