1use crate::color::*;
2use crate::defs::*;
3
4#[derive(Clone, Copy)]
5#[repr(C)]
6pub struct Paint {
7 xform: LocalTransform, glow: f32,
10 pub image: i32,
11
12 inner_color: Color, outer_color: Color, }
15
16impl Paint {
17 #[allow(dead_code)]
18 pub fn apply(&self, p: LocalPoint) -> Color {
19 let local_point = self.xform.transform_point(p);
20 let d = local_point
21 .clamp(LocalPoint::zero(), LocalPoint::new(1.0, 1.0))
22 .x;
23
24 self.inner_color.mix(self.outer_color, d)
25 }
26
27 pub fn solid_color(color: Color) -> Self {
28 Self {
29 xform: LocalTransform::identity(),
30 inner_color: color,
31 outer_color: color,
32 image: -1,
33 glow: 0.0,
34 }
35 }
36
37 pub fn linear_gradient(
38 start: LocalPoint,
39 end: LocalPoint,
40 inner_color: Color,
41 outer_color: Color,
42 glow: f32,
43 ) -> Self {
44 let mut d = end - start;
46 if d.length() < 0.0001 {
47 d = LocalVector::new(0.0, 1.0);
48 }
49
50 let xform = LocalTransform::new(d.x, d.y, -d.y, d.x, start.x, start.y)
51 .inverse()
52 .unwrap();
53
54 Self {
55 xform,
56 inner_color,
57 outer_color,
58 image: -1,
59 glow,
60 }
61 }
62}
63
64#[cfg(test)]
65mod tests {
66
67 use super::*;
68
69 #[test]
70 fn test_paint_size() {
71 assert_eq!(std::mem::size_of::<Paint>(), 64);
72 }
73
74 #[test]
75 fn test_linear_gradient() {
76 {
77 let paint = Paint::linear_gradient(
78 LocalPoint::new(0.0, 0.0),
79 LocalPoint::new(1.0, 0.0),
80 Color::gray(0.0),
81 Color::gray(1.0),
82 0.0,
83 );
84
85 assert_eq!(paint.apply(LocalPoint::new(0.0, 0.0)), Color::gray(0.0));
86 assert_eq!(paint.apply(LocalPoint::new(0.5, 0.0)), Color::gray(0.5));
87 assert_eq!(paint.apply(LocalPoint::new(1.0, 0.0)), Color::gray(1.0));
88 }
89
90 {
91 let paint = Paint::linear_gradient(
92 LocalPoint::new(0.0, 0.0),
93 LocalPoint::new(0.0, 1.0),
94 Color::gray(0.0),
95 Color::gray(1.0),
96 0.0,
97 );
98
99 assert_eq!(paint.apply(LocalPoint::new(0.0, 0.0)), Color::gray(0.0));
100 assert_eq!(paint.apply(LocalPoint::new(0.0, 1.0)), Color::gray(1.0));
101 }
102
103 {
104 let paint = Paint::linear_gradient(
105 LocalPoint::new(1.0, 0.0),
106 LocalPoint::new(2.0, 0.0),
107 Color::gray(0.0),
108 Color::gray(1.0),
109 0.0,
110 );
111
112 assert_eq!(paint.apply(LocalPoint::new(0.0, 0.0)), Color::gray(0.0));
113 assert_eq!(paint.apply(LocalPoint::new(1.0, 0.0)), Color::gray(0.0));
114 assert_eq!(paint.apply(LocalPoint::new(1.5, 0.0)), Color::gray(0.5));
115 assert_eq!(paint.apply(LocalPoint::new(2.0, 0.0)), Color::gray(1.0));
116 assert_eq!(paint.apply(LocalPoint::new(3.0, 0.0)), Color::gray(1.0));
117 }
118 }
119}