minifb_geometry/
lib.rs

1use bresenham::Bresenham;
2use error::DrawError;
3mod error;
4
5
6/// A struct representing a geometry drawer.
7pub struct GeometryDrawer {
8    window_width: usize,
9}
10
11impl GeometryDrawer {
12    /// Creates a new `GeometryDrawer` instance.
13    ///
14    /// # Arguments
15    ///
16    /// * `window_width` - The width of the window.
17    ///
18    /// # Returns
19    ///
20    /// A new `GeometryDrawer` instance.
21    pub fn new(window_width: usize) -> Self {
22        Self { window_width }
23    }
24
25    /// Draws a box on the buffer.
26    ///
27    /// # Arguments
28    ///
29    /// * `buf` - The buffer to draw on.
30    /// * `start_x` - The starting x-coordinate of the box.
31    /// * `start_y` - The starting y-coordinate of the box.
32    /// * `end_x` - The ending x-coordinate of the box.
33    /// * `end_y` - The ending y-coordinate of the box.
34    /// * `color` - The color of the box.
35    ///
36    /// # Returns
37    ///
38    /// Returns `Ok(())` if the box is successfully drawn, or a `DrawError` if an error occurs.
39    pub fn draw_box(
40        &self,
41        buf: &mut Vec<u32>,
42        start_x: usize,
43        start_y: usize,
44        end_x: usize,
45        end_y: usize,
46        color: usize,
47    ) -> Result<(), DrawError> {
48        for i in start_x..end_x {
49            for j in start_y..end_y {
50                self.draw_pixel(buf, i, j, color)?;
51            }
52        }
53        Ok(())
54    }
55
56    /// Clears the screen.
57    /// 
58    /// # Arguments
59    /// 
60    /// * `buf` - The buffer to clear.
61    /// * `start_x` - The starting x-coordinate of the screen.
62    /// * `start_y` - The starting y-coordinate of the screen.
63    /// * `end_x` - The ending x-coordinate of the screen.
64    /// * `end_y` - The ending y-coordinate of the screen.
65    /// 
66    /// # Returns
67    /// 
68    /// Returns `Ok(())` if the screen is successfully cleared, or a `DrawError` if an error occurs.
69    pub fn screen_clear(
70        &self,
71        buf: &mut Vec<u32>,
72        start_x: usize,
73        start_y: usize,
74        end_x: usize,
75        end_y: usize,
76    ) -> Result<(), DrawError>{
77        self.draw_box( buf, start_x, start_y, end_x, end_y, 0x00_00_00)
78    }
79
80    /// Draws a line on the buffer. 
81    ///  
82    /// # Arguments
83    /// 
84    /// * `buf` - The buffer to draw on.
85    /// * `start_x` - The starting x-coordinate of the line.
86    /// * `start_y` - The starting y-coordinate of the line.
87    /// * `end_x` - The ending x-coordinate of the line.
88    /// * `end_y` - The ending y-coordinate of the line.
89    /// * `color` - The color of the line.
90    /// 
91    /// # Returns
92    /// 
93    /// Returns `Ok(())` if the line is successfully drawn, or a `DrawError` if an error occurs.
94    pub fn draw_line(
95        &self,
96        buf: &mut Vec<u32>,
97        start_x: usize,
98        start_y: usize,
99        end_x: usize,
100        end_y: usize,
101        color: usize,
102    ) -> Result<(), DrawError>{
103        for (x, y) in Bresenham::new(
104            (start_x as isize, start_y as isize),
105            (end_x as isize, end_y as isize),
106        ) {
107            self.draw_pixel(buf, x as usize, y as usize, color)?;
108        }
109        Ok(())
110    }
111
112    /// Draws a rectangle on the buffer.
113    /// 
114    /// # Arguments
115    /// 
116    /// * `buf` - The buffer to draw on.
117    /// * `start_x` - The starting x-coordinate of the rectangle.
118    /// * `start_y` - The starting y-coordinate of the rectangle.
119    /// * `end_x` - The ending x-coordinate of the rectangle.
120    /// * `end_y` - The ending y-coordinate of the rectangle.           
121    /// * `border_thickness` - The thickness of the border of the rectangle.
122    /// * `color` - The color of the rectangle.
123    /// 
124    /// # Returns
125    /// 
126    /// Returns `Ok(())` if the rectangle is successfully drawn, or a `DrawError` if an error occurs.
127    pub fn draw_rectangle(
128        &self,
129        buf: &mut Vec<u32>,
130        start_x: usize,
131        start_y: usize,
132        end_x: usize,
133        end_y: usize,
134        border_thickness: usize,
135        color: usize,
136    ) -> Result<(), DrawError>{
137        for i in 0..border_thickness{
138            self.draw_line(buf, start_x + i, start_y, start_x + i, end_y, color)?; 
139            self.draw_line(buf, end_x - i -1, start_y, end_x - i -1, end_y, color)?;                  
140            self.draw_line(buf, start_x, start_y + i, end_x, start_y + i, color)?;  
141            self.draw_line(buf, start_x, end_y - i - 1, end_x, end_y - i - 1, color)?;
142        }
143        Ok(())
144    }
145
146    /// Draws a circle on the buffer.
147    /// 
148    /// # Arguments
149    /// 
150    /// * `buf` - The buffer to draw on.
151    /// * `start_x` - The starting x-coordinate of the circle.
152    /// * `start_y` - The starting y-coordinate of the circle.
153    /// * `radius` - The radius of the circle.
154    /// * `color` - The color of the circle.
155    /// 
156    /// # Returns
157    /// 
158    /// Returns `Ok(())` if the circle is successfully drawn, or a `DrawError` if an error occurs.
159    pub fn draw_circle(
160        &self,
161        buf: &mut Vec<u32>,
162        start_x: usize,
163        start_y: usize,
164        radius: usize,
165        color: usize,
166    ) -> Result<(), DrawError>{
167        let mut d: isize = 3 - 2 * radius as isize;
168        let mut x  = 0;
169        let mut y = radius;
170        while y >= x {
171            x += 1;
172            if d>0 {
173                y -= 1;
174                d = d + 4 * (x as isize - y as isize)  + 10;
175            }
176            else {
177                d = d + 4 * x as isize + 6;
178            }
179            self.draw_pixel(buf, start_x + x, start_y + y, color)?;
180            self.draw_pixel(buf, start_x - x, start_y + y, color)?;
181            self.draw_pixel(buf, start_x + x, start_y - y, color)?;
182            self.draw_pixel(buf, start_x - x, start_y - y, color)?;
183            self.draw_pixel(buf, start_x + y, start_y + x, color)?;
184            self.draw_pixel(buf, start_x - y, start_y + x, color)?;
185            self.draw_pixel(buf, start_x + y, start_y - x, color)?;
186            self.draw_pixel(buf, start_x - y, start_y - x, color)?;
187        }
188        Ok(())
189    }
190
191    /// Draws a pixel on the buffer.
192    /// 
193    /// # Arguments
194    /// 
195    /// * `buf` - The buffer to draw on.
196    /// * `x` - The x-coordinate of the pixel.
197    /// * `y` - The y-coordinate of the pixel.
198    /// * `color` - The color of the pixel.
199    /// 
200    /// # Returns
201    /// 
202    /// Returns `Ok(())` if the pixel is successfully drawn, or a `DrawError` if an error occurs.
203    fn draw_pixel(
204        &self,
205        buf: &mut Vec<u32>,
206        x: usize,
207        y: usize,
208        color: usize
209    ) -> Result<(), DrawError>{
210        if (y * self.window_width + x ) < buf.len(){
211            buf[y  * self.window_width + x ] = color as u32;
212        }
213        else {
214            return Err(DrawError::OutOfBounds(format!("x: {x} y: {y}").to_string()));
215        }
216        Ok(())
217    }
218
219    
220}
221
222
223
224
225
226
227
228
229