1use crate::Shape;
2
3pub const DOTS: [[u16; 2]; 4] = [
17 [0x0001, 0x0008],
18 [0x0002, 0x0010],
19 [0x0004, 0x0020],
20 [0x0040, 0x0080],
21];
22pub const BRAILLE_OFFSET: u16 = 0x2800;
23
24pub struct Grid {
25 width: usize,
26 cells: Vec<u16>,
27}
28
29impl Grid {
30 pub fn new(width: usize, height: usize) -> Grid {
31 Grid {
32 width,
33 cells: vec![BRAILLE_OFFSET; width * height],
34 }
35 }
36
37 pub fn to_string(&self) -> String {
38 let mut buf = String::new();
39 for (i, cell) in self.cells.iter().enumerate() {
40 if i != 0 && i % self.width == 0 {
41 buf.push('\n');
42 }
43 let ch = String::from_utf16(&[*cell]).unwrap();
44 if ch == "\u{2800}" {
45 buf.push(' ');
46 } else {
47 buf.push_str(&ch);
48 }
49 }
50 buf
51 }
52
53 pub fn reset(&mut self) {
54 for c in &mut self.cells {
55 *c = BRAILLE_OFFSET;
56 }
57 }
58}
59
60pub struct Context {
63 width: f32,
64 height: f32,
65 x_bounds: (f32, f32),
66 y_bounds: (f32, f32),
67 grid: Grid,
68}
69
70impl Context {
71 pub fn new(width: f32, height: f32) -> Self {
72 let width = width * 2.0;
73 Context {
74 width,
75 height,
76 x_bounds: (0.0, width),
77 y_bounds: (0.0, height),
78 grid: Grid::new(width as usize, height as usize),
79 }
80 }
81
82 pub fn to_string(&self) -> String {
83 self.grid.to_string()
84 }
85
86 pub fn draw<'b, S>(&mut self, shape: &'b S)
88 where
89 S: Shape<'b>,
90 {
91 let (left, right) = self.x_bounds;
92 let (top, bottom) = self.y_bounds;
93 for (x, y) in shape
94 .points()
95 .map(|(x, y)| (2.0 * x, y))
96 .filter(|&(x, y)| x >= left && x < right && y >= top && y < bottom)
97 {
98 let dy =
99 ((top - y) * (self.height) * 4.0 / (top - bottom)) as usize;
100 let dx =
101 ((x - left) * (self.width) * 2.0 / (right - left)) as usize;
102 let index = dy / 4 * self.width as usize + dx / 2;
103 let dy_index = dy % 4;
104 let dx_index = dx % 2;
105 let braille = DOTS[dy_index][dx_index];
106 self.grid.cells[index] |= braille;
107 }
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::line::Line;
115
116 #[test]
117 fn draw_cell_horizontal_line() {
118 let mut context = Context::new(0.5, 1.0);
119
120 context.draw(&Line {
121 x1: 0.0,
122 y1: 0.5,
123 x2: 1.0,
124 y2: 0.5,
125 });
126 let result = context.to_string();
127 assert_eq!(result, "⠤");
128 }
129
130 #[test]
131 fn draw_cell_vertical_line() {
132 let mut context = Context::new(0.5, 1.0);
133
134 context.draw(&Line {
135 x1: 0.125,
136 y1: 0.0,
137 x2: 0.125,
138 y2: 1.0,
139 });
140 let result = context.to_string();
141 assert_eq!(result, "⡇");
142 }
143
144 #[test]
145 fn draw_cell_slant_line1() {
146 let mut context = Context::new(0.5, 1.0);
147
148 context.draw(&Line {
149 x1: 0.0,
150 y1: 0.0,
151 x2: 0.5,
152 y2: 1.0,
153 });
154 let result = context.to_string();
155 assert_eq!(result, "⢣");
156 }
157 #[test]
158 fn draw_cell_slant_line2() {
159 let mut context = Context::new(0.5, 1.0);
160
161 context.draw(&Line {
162 x1: 0.0,
163 y1: 1.0,
164 x2: 0.5,
165 y2: 0.0,
166 });
167 let result = context.to_string();
168 assert_eq!(result, "⡰");
169 }
170
171 #[test]
172 fn draw_cell_slant_line3() {
173 let mut context = Context::new(0.5, 1.0);
174
175 context.draw(&Line {
176 x1: 0.0,
177 y1: 0.75,
178 x2: 0.5,
179 y2: 0.375,
180 });
181 let result = context.to_string();
182 assert_eq!(result, "⡠");
183 }
184
185 #[test]
186 fn draw_horizontal_lines() {
187 let width = 10;
188 let height = 1;
189 let mut context = Context::new(width as f32, height as f32);
190
191 context.draw(&Line {
192 x1: 0.0,
193 y1: 0.5,
194 x2: width as f32,
195 y2: 0.5,
196 });
197 let result = context.to_string();
198 assert_eq!(result, "⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤");
199 }
200
201 #[test]
202 fn draw_vertical_lines() {
203 let width = 1.0;
204 let height = 10.0;
205 let mut context = Context::new(width as f32, height as f32);
206
207 context.draw(&Line {
208 x1: 0.5,
209 y1: 0.0,
210 x2: 0.5,
211 y2: height,
212 });
213 let result = context.to_string();
214 let expected =
215 [" ⡇", " ⡇", " ⡇", " ⡇", " ⡇", " ⡇", " ⡇", " ⡇", " ⡇", " ⡇"];
216 assert_eq!(result, expected.join("\n"));
217 }
218
219 #[test]
220 fn draw_slash_lines() {
221 let width = 10.0;
222 let height = 10.0;
223
224 let mut context = Context::new(width as f32, height as f32);
225 context.draw(&Line {
226 x1: 0.0,
227 y1: 0.0,
228 x2: width,
229 y2: height,
230 });
231 let result = context.to_string();
232
233 let expected = [
234 "⠑⢄ ",
235 " ⠑⢄ ",
236 " ⠑⢄ ",
237 " ⠑⢄ ",
238 " ⠑⢄ ",
239 " ⠑⢄ ",
240 " ⠑⢄ ",
241 " ⠑⢄ ",
242 " ⠑⢄ ",
243 " ⠑⢄",
244 ];
245
246 assert_eq!(result, expected.join("\n"));
247 }
248
249 #[test]
250 fn draw_slash_lines2() {
251 let width = 10.0;
252 let height = 10.0;
253 let mut context = Context::new(width as f32, height as f32);
254
255 context.draw(&Line {
256 x1: width,
257 y1: height,
258 x2: 0.0,
259 y2: 0.0,
260 });
261 let result = context.to_string();
262 println!("{}", result);
263 let expected = [
264 "⠐⢄ ",
265 " ⠑⢄ ",
266 " ⠑⢄ ",
267 " ⠑⢄ ",
268 " ⠑⢄ ",
269 " ⠑⢄ ",
270 " ⠑⢄ ",
271 " ⠑⢄ ",
272 " ⠑⢄ ",
273 " ⠑⢄",
274 ];
275 assert_eq!(result, expected.join("\n"));
276 }
277
278 #[test]
279 fn draw_slant_lines1() {
280 let width = 10.0;
281 let height = 10.0;
282 let mut context = Context::new(width as f32, height as f32);
283
284 context.draw(&Line {
285 x1: 0.0,
286 y1: height,
287 x2: width,
288 y2: 0.0,
289 });
290 let result = context.to_string();
291 println!("{}", result);
292
293 let expected = [
294 " ⢀⠔",
295 " ⢀⠔⠁ ",
296 " ⢀⠔⠁ ",
297 " ⢀⠔⠁ ",
298 " ⢀⠔⠁ ",
299 " ⢀⠔⠁ ",
300 " ⢀⠔⠁ ",
301 " ⢀⠔⠁ ",
302 " ⢀⠔⠁ ",
303 "⢀⠔⠁ ",
304 ];
305
306 assert_eq!(result, expected.join("\n"));
307 }
308
309 #[test]
310 fn draw_slant_lines2() {
311 let width = 10.0;
312 let height = 10.0;
313 let mut context = Context::new(width as f32, height as f32);
314
315 context.draw(&Line {
316 x1: width - 0.5,
317 y1: 0.0,
318 x2: 0.0,
319 y2: height,
320 });
321 let result = context.to_string();
322 println!("{}", result);
323
324 let expected = [
325 " ⢀⠔⠁",
326 " ⢀⠔⠁ ",
327 " ⢀⠔⠁ ",
328 " ⢀⠔⠁ ",
329 " ⢀⠔⠁ ",
330 " ⡠⠊ ",
331 " ⡠⠊ ",
332 " ⡠⠊ ",
333 " ⡠⠊ ",
334 "⡠⠊ ",
335 ];
336
337 assert_eq!(result, expected.join("\n"));
338 }
339}