astrelis_geometry/
fill.rs1use crate::Paint;
6use astrelis_render::Color;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
10pub enum FillRule {
11 #[default]
15 NonZero,
16 EvenOdd,
20}
21
22#[derive(Debug, Clone, PartialEq)]
24pub struct Fill {
25 pub paint: Paint,
27 pub rule: FillRule,
29 pub opacity: f32,
31}
32
33impl Fill {
34 pub fn solid(color: Color) -> Self {
36 Self {
37 paint: Paint::Solid(color),
38 rule: FillRule::NonZero,
39 opacity: 1.0,
40 }
41 }
42
43 pub fn from_paint(paint: Paint) -> Self {
45 Self {
46 paint,
47 rule: FillRule::NonZero,
48 opacity: 1.0,
49 }
50 }
51
52 pub fn with_rule(mut self, rule: FillRule) -> Self {
54 self.rule = rule;
55 self
56 }
57
58 pub fn with_opacity(mut self, opacity: f32) -> Self {
60 self.opacity = opacity.clamp(0.0, 1.0);
61 self
62 }
63
64 pub fn effective_color(&self) -> Option<Color> {
66 match &self.paint {
67 Paint::Solid(color) => Some(Color::rgba(
68 color.r,
69 color.g,
70 color.b,
71 color.a * self.opacity,
72 )),
73 _ => None,
74 }
75 }
76}
77
78impl Default for Fill {
79 fn default() -> Self {
80 Self::solid(Color::BLACK)
81 }
82}
83
84impl From<Color> for Fill {
85 fn from(color: Color) -> Self {
86 Self::solid(color)
87 }
88}
89
90impl From<Paint> for Fill {
91 fn from(paint: Paint) -> Self {
92 Self::from_paint(paint)
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_solid_fill() {
102 let fill = Fill::solid(Color::RED);
103 assert_eq!(fill.opacity, 1.0);
104 assert!(matches!(fill.paint, Paint::Solid(_)));
105 }
106
107 #[test]
108 fn test_fill_opacity() {
109 let fill = Fill::solid(Color::RED).with_opacity(0.5);
110 let effective = fill.effective_color().unwrap();
111 assert!((effective.a - 0.5).abs() < 0.01);
112 }
113}