graphics_rs/
simple_canvas.rs1use std::{fs::File, io::Write};
2
3use crate::color;
4use crate::{
5 color::Color,
6 traits::{
7 canvas::Canvas, handles_draw_request::HandlesDrawRequest, is_color::IsColor,
8 requests_draw::RequestDraw, shape::Shape,
9 },
10};
11
12pub struct SimpleCanvas<'a> {
13 buffer: Vec<Color>,
14 width: usize,
15 height: usize,
16 color: Color,
17 antialiasing: bool,
18 antialiasing_resolution: usize,
19 draw_request_handler: Option<&'a dyn HandlesDrawRequest>,
20}
21
22impl<'a> SimpleCanvas<'a> {
23 pub fn new(
24 width: usize,
25 height: usize,
26 fill_color: Option<Color>,
27 antialiasing: bool,
28 antialiasing_resolution: usize,
29 ) -> Self {
30 let antialiasing_resolution = antialiasing_resolution.clamp(1, usize::MAX);
31 let fill_color = fill_color.unwrap_or(color::BLACK);
32
33 Self {
34 buffer: vec![fill_color; width * height],
35 width,
36 height,
37 color: fill_color,
38 antialiasing,
39 draw_request_handler: None,
40 antialiasing_resolution: antialiasing_resolution,
41 }
42 }
43
44 pub fn size(&self) -> usize {
45 self.width * self.height
46 }
47
48 pub fn save(&mut self, path: &str) -> std::io::Result<()> {
49 let mut file = File::create(path)?;
50 File::write(
51 &mut file,
52 format!("P6\n{} {} 255\n", self.width, self.height).as_bytes(),
53 )?;
54
55 for i in 0..self.size() {
56 let pixel = self.color_at(i);
57 let red = pixel.red();
58 let green = pixel.green();
59 let blue = pixel.blue();
60
61 File::write(&mut file, &[red, green, blue])?;
62 }
63
64 Ok(())
65 }
66}
67
68impl<'a> Canvas for SimpleCanvas<'a> {
69 fn draw_shape(&mut self, shape: &mut impl Shape) {
70 shape.draw_to(self);
71 }
72
73 fn change_color(&mut self, color: Color) {
74 self.color = color
75 }
76
77 fn clamp_row(&self, row: i64) -> i64 {
78 row.clamp(0, (self.height - 1) as i64)
79 }
80
81 fn clamp_col(&self, col: i64) -> i64 {
82 col.clamp(0, (self.width - 1) as i64)
83 }
84
85 fn color_at(&self, index: usize) -> Color {
86 return self.buffer[index];
87 }
88
89 fn width(&self) -> usize {
90 self.width
91 }
92
93 fn height(&self) -> usize {
94 self.height
95 }
96
97 fn fits_inside(&self, row: i64, col: i64) -> bool {
98 return row < self.height as i64 && col < self.width as i64;
99 }
100
101 fn fill(&mut self) {
102 for row in 0..self.height {
103 for col in 0..self.width {
104 self.set_pixel_color(row, col, self.color);
105 }
106 }
107 }
108
109 fn antialiasing(&self) -> bool {
110 self.antialiasing
111 }
112
113 fn resolution(&self) -> usize {
114 self.antialiasing_resolution
115 }
116
117 fn color(&self) -> Color {
118 self.color
119 }
120
121 fn set_pixel(&mut self, row: usize, col: usize) {
122 self.set_pixel_color(row, col, self.color);
123 }
124
125 fn set_pixel_color(&mut self, row: usize, col: usize, color: Color) {
126 if self.fits_inside(row as i64, col as i64) {
127 let index = self.width * row + col;
128 let old_color = self.color_at(index);
129
130 self.buffer[index] = old_color.mix(color);
131 }
132 }
133
134 fn buffer_mut_slice(&mut self) -> &mut [Color] {
135 self.buffer.as_mut_slice()
136 }
137}
138
139impl<'a> RequestDraw<'a> for SimpleCanvas<'a> {
140 fn set_draw_request_handler<T: HandlesDrawRequest>(&mut self, handler: &'a T) {
141 self.draw_request_handler = Some(handler)
142 }
143
144 fn request_draw(&self) {
145 if let Some(draw_handler) = self.draw_request_handler {
146 draw_handler.draw();
147 }
148 }
149}