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}