glance_core/drawing/
shapes.rs1use super::traits::Drawable;
2use crate::Result;
3
4pub struct Circle {
8 pub position: [u32; 2],
10 pub color: [u8; 4],
12 pub radius: u32,
14 pub filled: bool,
16 pub thickness: u32,
18}
19
20impl Drawable for Circle {
21 fn draw_on(&self, image: &mut crate::img::Image) -> Result<()> {
22 let (cx, cy) = (self.position[0] as i32, self.position[1] as i32);
23 let radius = self.radius as i32;
24 let thickness = self.thickness as i32;
25 let dims = image.dimensions();
26
27 let outer_radius = radius + thickness;
28 let outer_radius_sq = outer_radius.pow(2);
29 let inner_radius_sq = radius.pow(2);
30
31 for dy in -outer_radius..outer_radius {
32 for dx in -outer_radius..outer_radius {
33 let nx = cx + dx;
34 let ny = cy + dy;
35
36 if nx < 0 || ny < 0 {
38 continue;
39 }
40
41 let (nx, ny) = (nx as u32, ny as u32);
42 if nx >= dims[0] || ny >= dims[1] {
43 continue;
44 }
45
46 let distance_sq = dx * dx + dy * dy;
47 let draw_pixel = match self.filled {
49 true => distance_sq <= inner_radius_sq,
50 false => distance_sq <= outer_radius_sq && distance_sq >= inner_radius_sq,
51 };
52
53 if draw_pixel {
54 image.alpha_blend_pixel([nx, ny], self.color)?;
55 }
56 }
57 }
58 Ok(())
59 }
60}
61
62pub struct AABB {
66 pub position: [u32; 2],
68 pub size: [u32; 2],
70 pub color: [u8; 4],
72 pub filled: bool,
74 pub thickness: u32,
76}
77
78impl Drawable for AABB {
79 fn draw_on(&self, image: &mut crate::img::Image) -> Result<()> {
80 let (cx, cy) = (self.position[0] as i32, self.position[1] as i32);
81 let dims = image.dimensions();
82 let width = self.size[0] as i32;
83 let height = self.size[1] as i32;
84 let thickness = self.thickness as i32;
85
86 let left_x = cx - thickness;
87 let right_x = cx + width + thickness;
88 let top_y = cy - thickness;
89 let bottom_y = cy + height + thickness;
90
91 for x in left_x..right_x {
93 for y in top_y..bottom_y {
94 if x < 0 || y < 0 {
96 continue;
97 }
98
99 let nx = x as u32;
100 let ny = y as u32;
101
102 if nx >= dims[0] || ny >= dims[1] {
103 continue;
104 }
105
106 let on_left_edge = x - left_x <= thickness;
108 let on_right_edge = right_x - x <= thickness;
109 let on_top_edge = y - top_y < thickness;
110 let on_bottom_edge = bottom_y - y <= thickness;
111 let draw_pixel =
112 self.filled || on_left_edge || on_right_edge || on_top_edge || on_bottom_edge;
113
114 if draw_pixel {
115 image.alpha_blend_pixel([nx, ny], self.color)?;
116 }
117 }
118 }
119
120 Ok(())
121 }
122}
123
124pub struct Line {
127 pub start: [u32; 2],
129 pub end: [u32; 2],
131 pub color: [u8; 4],
133 pub thickness: u32,
135}
136
137impl Drawable for Line {
138 fn draw_on(&self, image: &mut crate::img::Image) -> Result<()> {
139 let [x0, y0] = self.start;
140 let [x1, y1] = self.end;
141
142 let dims = image.dimensions();
143
144 let x0 = x0 as i32;
145 let y0 = y0 as i32;
146 let x1 = x1 as i32;
147 let y1 = y1 as i32;
148 let thickness = self.thickness as i32;
149 let half_thickness = thickness / 2;
150
151 let dx = (x1 - x0).abs();
153 let dy = -(y1 - y0).abs();
154 let sx = if x0 < x1 { 1 } else { -1 };
156 let sy = if y0 < y1 { 1 } else { -1 };
157 let mut err = dx + dy;
158 let mut x = x0;
159 let mut y = y0;
160
161 loop {
162 for tx in -half_thickness..=half_thickness {
163 for ty in -half_thickness..=half_thickness {
164 let nx = x + tx;
165 let ny = y + ty;
166
167 if nx < 0 || ny < 0 {
169 continue;
170 }
171
172 let (nx, ny) = (nx as u32, ny as u32);
173 if nx >= dims[0] || ny >= dims[1] {
174 continue;
175 }
176
177 image.alpha_blend_pixel([nx, ny], self.color)?;
178 }
179 }
180
181 if x == x1 && y == y1 {
183 break;
184 }
185
186 let err_twice = 2 * err;
187 if err_twice >= dy {
188 err += dy;
189 x += sx;
190 }
191 if err_twice <= dx {
192 err += dx;
193 y += sy;
194 }
195 }
196
197 Ok(())
198 }
199}