drawing_stuff/
canvas.rs

1use crate::color::{RGB, RGBA};
2
3/// Trait for drawing anything arbitrary onto a [`Canvas`].
4///
5/// # Examples
6///
7/// ```
8/// use drawing_stuff::canvas::{Canvas, Draw};
9/// use drawing_stuff::color::RGBA;
10///
11/// pub struct Circle {
12///     pub center: (isize, isize),
13///     pub radius: u32,
14///     pub solid: bool,
15///
16///     pub color: RGBA,
17/// }
18///
19/// impl Draw for Circle {
20///     fn draw(&self, canvas: &mut Canvas) {
21///        match self.solid {
22///           true => canvas.draw_circle_solid(self.center.0, self.center.1, self.radius, self.color),
23///           false => canvas.draw_circle(self.center.0, self.center.1, self.radius, self.color),
24///       }
25///     }
26/// }
27/// ```
28pub trait Draw {
29    /// Draws onto a [`Canvas`].
30    fn draw(&self, canvas: &mut Canvas);
31}
32
33#[derive(Debug, Clone)]
34/// A [`Canvas`] is just a glorified pixel buffer with some usefull functionality.
35pub struct Canvas {
36    width: usize,
37    height: usize,
38
39    buffer: Vec<RGB>,
40}
41
42impl Canvas {
43    /// Creates a new black canvas.
44    ///
45    /// # Examples
46    ///
47    /// ```
48    /// use drawing_stuff::canvas::Canvas;
49    ///
50    /// const WIDTH: usize = 1080;
51    /// const HEIGHT: usize = 720;
52    ///
53    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
54    /// ```
55    pub fn new(width: usize, height: usize) -> Self {
56        Canvas {
57            width,
58            height,
59            buffer: vec![RGB { r: 0, g: 0, b: 0 }; width * height],
60        }
61    }
62}
63
64impl Canvas {
65    /// Returns the width of the canvas.
66    ///
67    /// # Examples
68    ///
69    /// ```
70    /// use drawing_stuff::canvas::Canvas;
71    ///
72    /// const WIDTH: usize = 1080;
73    /// const HEIGHT: usize = 720;
74    ///
75    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
76    ///
77    /// assert_eq!(WIDTH, canvas.width());
78    /// ```
79    pub fn width(&self) -> usize {
80        self.width
81    }
82
83    /// Returns the height of the canvas.
84    ///
85    /// # Examples
86    ///
87    /// ```
88    /// use drawing_stuff::canvas::Canvas;
89    ///
90    /// const WIDTH: usize = 1080;
91    /// const HEIGHT: usize = 720;
92    ///
93    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
94    ///
95    /// assert_eq!(HEIGHT, canvas.height());
96    /// ```
97    pub fn height(&self) -> usize {
98        self.height
99    }
100
101    /// Returns a reference to the pixel buffer of the canvas.
102    ///
103    /// # Examples
104    ///
105    /// ```
106    /// use drawing_stuff::canvas::Canvas;
107    ///
108    /// const WIDTH: usize = 1080;
109    /// const HEIGHT: usize = 720;
110    ///
111    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
112    ///
113    /// let buffer = canvas.buffer();
114    /// ```
115    pub fn buffer(&self) -> &Vec<RGB> {
116        &self.buffer
117    }
118
119    /// Returns a mutabel reference to the pixel buffer of the canvas.
120    ///
121    /// # Examples
122    ///
123    /// ```
124    /// use drawing_stuff::canvas::Canvas;
125    /// use drawing_stuff::color::RGB;
126    ///
127    /// const WIDTH: usize = 1080;
128    /// const HEIGHT: usize = 720;
129    ///
130    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
131    ///
132    /// let buffer = canvas.buffer_mut();
133    /// for pixel in buffer {
134    ///     *pixel = RGB { r: 255, g: 255, b: 255 };
135    /// }
136    /// ```
137    pub fn buffer_mut(&mut self) -> &mut Vec<RGB> {
138        &mut self.buffer
139    }
140
141    /// Returns the pixel buffer as a 32-bit buffer in the format `0RGB`.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// use drawing_stuff::canvas::Canvas;
147    ///
148    /// const WIDTH: usize = 1080;
149    /// const HEIGHT: usize = 720;
150    ///
151    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
152    ///
153    /// let buffer = canvas.buffer_u32();
154    /// ```
155    pub fn buffer_u32(&self) -> Vec<u32> {
156        self.buffer
157            .iter()
158            .map(|c| (c.r as u32) << 16 | (c.g as u32) << 8 | (c.b as u32))
159            .collect::<Vec<u32>>()
160    }
161
162    /// Checks if the pixel specified lays inside of the canvas.
163    ///
164    /// # Examples
165    ///
166    /// ```
167    /// use drawing_stuff::canvas::Canvas;
168    ///
169    /// const WIDTH: usize = 1080;
170    /// const HEIGHT: usize = 720;
171    ///
172    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
173    ///
174    /// let in_bound = canvas.pixel_inside(200, 100);
175    /// assert_eq!(true, in_bound);
176    /// ```
177    pub fn pixel_inside(&self, x: isize, y: isize) -> bool {
178        x >= 0 && x < self.width as isize && y >= 0 && y < self.height as isize
179    }
180
181    /// Returns the color of the pixel at the specified position.
182    ///
183    /// Returns `None` if position is not inside the canvas.
184    ///
185    /// # Examples
186    ///
187    /// ```
188    /// use drawing_stuff::canvas::Canvas;
189    ///
190    /// const WIDTH: usize = 1080;
191    /// const HEIGHT: usize = 720;
192    ///
193    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
194    ///
195    /// let pixel = canvas.get(200, 100);
196    ///
197    /// assert_eq!(true, pixel.is_some());
198    /// ```
199    pub fn get(&self, x: usize, y: usize) -> Option<&RGB> {
200        self.buffer.get(y * self.width + x)
201    }
202
203    /// Sets the color of the pixel at the specified position.
204    ///
205    /// Returns `None` if position is not inside the canvas.
206    ///
207    /// # Examples
208    ///
209    /// ```
210    /// use drawing_stuff::canvas::Canvas;
211    /// use drawing_stuff::color::RGB;
212    ///
213    /// const WIDTH: usize = 1080;
214    /// const HEIGHT: usize = 720;
215    ///
216    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
217    ///
218    /// let color = RGB { r: 255, g: 255, b: 255 };
219    /// let success = canvas.set(200, 100, color);
220    ///
221    /// assert_eq!(true, success.is_some());
222    /// ```
223    pub fn set(&mut self, x: usize, y: usize, color: RGB) -> Option<()> {
224        *self.buffer.get_mut(y * self.width + x)? = color;
225        Some(())
226    }
227
228    /// Fills the whole canvas with a given color.
229    ///
230    /// # Examples
231    ///
232    /// ```
233    /// use drawing_stuff::canvas::Canvas;
234    /// use drawing_stuff::color::RGB;
235    ///
236    /// const WIDTH: usize = 1080;
237    /// const HEIGHT: usize = 720;
238    ///
239    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
240    ///
241    /// let color = RGB { r: 255, g: 255, b: 255 };
242    /// canvas.fill(color);
243    /// ```
244    pub fn fill(&mut self, color: RGB) {
245        self.buffer = vec![color; self.width * self.height];
246    }
247}
248
249impl Canvas {
250    /// Draws anything arbitrary implementing the `Draw` trait onto the canvas.
251    ///
252    /// # Examples
253    ///
254    /// ```
255    /// use drawing_stuff::canvas::{Canvas, Draw};
256    /// use drawing_stuff::color::RGBA;
257    ///
258    /// pub struct Circle {
259    ///     pub center: (isize, isize),
260    ///     pub radius: u32,
261    ///     pub solid: bool,
262    ///
263    ///     pub color: RGBA,
264    /// }
265    ///
266    /// impl Draw for Circle {
267    ///     fn draw(&self, canvas: &mut Canvas) {
268    ///        match self.solid {
269    ///           true => canvas.draw_circle_solid(self.center.0, self.center.1, self.radius, self.color),
270    ///           false => canvas.draw_circle(self.center.0, self.center.1, self.radius, self.color),
271    ///       }
272    ///     }
273    /// }
274    ///
275    /// const WIDTH: usize = 1080;
276    /// const HEIGHT: usize = 720;
277    ///
278    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
279    ///
280    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
281    /// let circle = Circle {
282    ///     center: (200, 100),
283    ///     radius: 50,
284    ///     solid: true,
285    ///     color,
286    /// };
287    ///
288    /// canvas.draw(&circle);
289    /// // or
290    /// circle.draw(&mut canvas);
291    /// ```
292    pub fn draw<T>(&mut self, drawable: &T)
293    where
294        T: Draw,
295    {
296        drawable.draw(self);
297    }
298
299    /// Draws a single pixel onto the canvas.
300    ///
301    /// Returns `None` if position is not inside the canvas.
302    ///
303    /// # Examples
304    ///
305    /// ```
306    /// use drawing_stuff::canvas::Canvas;
307    /// use drawing_stuff::color::RGBA;
308    ///
309    /// const WIDTH: usize = 1080;
310    /// const HEIGHT: usize = 720;
311    ///
312    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
313    ///
314    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
315    /// let success = canvas.draw_pixel(200, 100, color);
316    ///
317    /// assert_eq!(true, success.is_some());
318    /// ```
319    pub fn draw_pixel(&mut self, x: isize, y: isize, color: RGBA) -> Option<()> {
320        if !self.pixel_inside(x, y) {
321            return None;
322        };
323
324        let old_color = self.get(x as usize, y as usize)?;
325        let new_color = old_color.add_rgba(color);
326        self.set(x as usize, y as usize, new_color)
327    }
328
329    /// Draws a line onto the canvas.
330    ///
331    /// # Examples
332    ///
333    /// ```
334    /// use drawing_stuff::canvas::Canvas;
335    /// use drawing_stuff::color::RGBA;
336    ///
337    /// const WIDTH: usize = 1080;
338    /// const HEIGHT: usize = 720;
339    ///
340    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
341    ///
342    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
343    /// canvas.draw_line(200, 100, 500, 700, color);
344    /// ```
345    pub fn draw_line(&mut self, x1: isize, y1: isize, x2: isize, y2: isize, color: RGBA) {
346        if x1 == x2 {
347            let (start_y, end_y) = if y1 < y2 { (y1, y2) } else { (y2, y1) };
348            for i in 0..(end_y - start_y) {
349                self.draw_pixel(x1, start_y + i, color);
350            }
351            return;
352        }
353
354        let dx = (x2 - x1).abs();
355        let dy = (y2 - y1).abs();
356
357        let abs_m = dy as f32 / dx as f32;
358        match abs_m <= 1.0 {
359            true => {
360                let (start_x, start_y, end_x, end_y) = if x1 < x2 {
361                    (x1, y1, x2, y2)
362                } else {
363                    (x2, y2, x1, y1)
364                };
365
366                let step = if start_y < end_y { 1 } else { -1 };
367
368                let a = 2 * dy;
369                let b = a - 2 * dx;
370                let mut p = a - dx;
371                self.draw_pixel(start_x, start_y, color);
372
373                let mut offset = 0isize;
374                for i in 1..=(end_x - start_x) {
375                    match p < 0 {
376                        true => {
377                            p += a;
378                        }
379                        false => {
380                            offset += step;
381                            p += b;
382                        }
383                    }
384
385                    self.draw_pixel(start_x + i, start_y + offset, color);
386                }
387            }
388            false => {
389                let (start_x, start_y, end_x, end_y) = if y1 < y2 {
390                    (x1, y1, x2, y2)
391                } else {
392                    (x2, y2, x1, y1)
393                };
394
395                let step = if start_x < end_x { 1 } else { -1 };
396
397                let a = 2 * dx;
398                let b = a - 2 * dy;
399                let mut p = a - dy;
400
401                self.draw_pixel(start_x, start_y, color);
402
403                let mut offset = 0isize;
404                for i in 1..=(end_y - start_y) {
405                    match p < 0 {
406                        true => {
407                            p += a;
408                        }
409                        false => {
410                            offset += step;
411                            p += b;
412                        }
413                    }
414
415                    self.draw_pixel(start_x + offset, start_y + i, color);
416                }
417            }
418        }
419    }
420
421    /// Draws a line with specified width onto the canvas.
422    /// Drawing the line as a filled polygon.
423    ///
424    /// # Examples
425    ///
426    /// ```
427    /// use drawing_stuff::canvas::Canvas;
428    /// use drawing_stuff::color::RGBA;
429    ///
430    /// const WIDTH: usize = 1080;
431    /// const HEIGHT: usize = 720;
432    ///
433    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
434    ///
435    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
436    /// canvas.draw_polyline(200, 100, 500, 700, 5, color);
437    /// ```
438    pub fn draw_polyline(
439        &mut self,
440        x1: isize,
441        y1: isize,
442        x2: isize,
443        y2: isize,
444        width: u32,
445        color: RGBA,
446    ) {
447        if width == 0 {
448            return;
449        }
450
451        if width == 1 {
452            self.draw_line(x1, y1, x2, y2, color);
453            return;
454        }
455
456        let dx = x2 - x1;
457        let dy = y2 - y1;
458
459        let d_len = ((dx * dx + dy * dy) as f32).sqrt();
460        let dx_n = dx as f32 / d_len;
461        let dy_n = dy as f32 / d_len;
462
463        let v1 = (
464            x1 - (dy_n * width as f32 / 2.0).round() as isize,
465            y1 + (dx_n * width as f32 / 2.0).round() as isize,
466        );
467        let v2 = (
468            x1 + (dy_n * width as f32 / 2.0).round() as isize,
469            y1 - (dx_n * width as f32 / 2.0).round() as isize,
470        );
471        let v3 = (
472            x2 + (dy_n * width as f32 / 2.0).round() as isize,
473            y2 - (dx_n * width as f32 / 2.0).round() as isize,
474        );
475        let v4 = (
476            x2 - (dy_n * width as f32 / 2.0).round() as isize,
477            y2 + (dx_n * width as f32 / 2.0).round() as isize,
478        );
479
480        let vertices = vec![v1, v2, v3, v4];
481
482        self.draw_polygon_solid(&vertices, true, color);
483    }
484
485    /// Draws a line with specified width and capped ends onto the canvas.
486    /// Drawing the line as a filled polygon with circles on both ends.
487    ///
488    /// # Examples
489    ///
490    /// ```
491    /// use drawing_stuff::canvas::Canvas;
492    /// use drawing_stuff::color::RGBA;
493    ///
494    /// const WIDTH: usize = 1080;
495    /// const HEIGHT: usize = 720;
496    ///
497    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
498    ///
499    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
500    /// canvas.draw_polyline_capped(200, 100, 500, 700, 5, color);
501    /// ```
502    pub fn draw_polyline_capped(
503        &mut self,
504        x1: isize,
505        y1: isize,
506        x2: isize,
507        y2: isize,
508        width: u32,
509        color: RGBA,
510    ) {
511        self.draw_polyline(x1, y1, x2, y2, width, color);
512        self.draw_circle_solid(x1, y1, width / 2, color);
513        self.draw_circle_solid(x2, y2, width / 2, color);
514    }
515
516    /// Draws a circle onto the canvas.
517    ///
518    /// # Examples
519    ///
520    /// ```
521    /// use drawing_stuff::canvas::Canvas;
522    /// use drawing_stuff::color::RGBA;
523    ///
524    /// const WIDTH: usize = 1080;
525    /// const HEIGHT: usize = 720;
526    ///
527    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
528    ///
529    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
530    /// canvas.draw_circle(200, 100, 15, color);
531    /// ```
532    pub fn draw_circle(&mut self, x: isize, y: isize, r: u32, color: RGBA) {
533        if r == 0 {
534            return;
535        }
536
537        let mut e = -(r as isize);
538        let mut x_offset = r as isize;
539        let mut y_offset = 0isize;
540
541        while y_offset <= x_offset {
542            self.draw_pixel(x + x_offset, y + y_offset, color);
543            self.draw_pixel(x + x_offset, y - y_offset, color);
544            self.draw_pixel(x - x_offset, y + y_offset, color);
545            self.draw_pixel(x - x_offset, y - y_offset, color);
546
547            self.draw_pixel(x + y_offset, y + x_offset, color);
548            self.draw_pixel(x + y_offset, y - x_offset, color);
549            self.draw_pixel(x - y_offset, y - x_offset, color);
550            self.draw_pixel(x - y_offset, y + x_offset, color);
551
552            e += 2 * y_offset + 1;
553            y_offset += 1;
554            if e >= 0 {
555                e -= 2 * x_offset - 1;
556                x_offset -= 1;
557            }
558        }
559    }
560
561    /// Draws a solid circle onto the canvas.
562    ///
563    /// # Examples
564    ///
565    /// ```
566    /// use drawing_stuff::canvas::Canvas;
567    /// use drawing_stuff::color::RGBA;
568    ///
569    /// const WIDTH: usize = 1080;
570    /// const HEIGHT: usize = 720;
571    ///
572    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
573    ///
574    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
575    /// canvas.draw_circle_solid(200, 100, 15, color);
576    /// ```
577    pub fn draw_circle_solid(&mut self, x: isize, y: isize, r: u32, color: RGBA) {
578        if r == 0 {
579            return;
580        }
581
582        let mut e = -(r as isize);
583        let mut x_offset = r as isize;
584        let mut y_offset = 0isize;
585
586        let dy = 2 * r;
587
588        let mut left_buff = vec![0isize; dy as usize + 1];
589        let mut right_buff = vec![0isize; dy as usize + 1];
590
591        while y_offset <= x_offset {
592            right_buff[(y + y_offset - (y - r as isize)) as usize] = x + x_offset;
593            right_buff[(y - y_offset - (y - r as isize)) as usize] = x + x_offset;
594            left_buff[(y + y_offset - (y - r as isize)) as usize] = x - x_offset;
595            left_buff[(y - y_offset - (y - r as isize)) as usize] = x - x_offset;
596
597            right_buff[(y + x_offset - (y - r as isize)) as usize] = x + y_offset;
598            right_buff[(y - x_offset - (y - r as isize)) as usize] = x + y_offset;
599            left_buff[(y + x_offset - (y - r as isize)) as usize] = x - y_offset;
600            left_buff[(y - x_offset - (y - r as isize)) as usize] = x - y_offset;
601
602            e += 2 * y_offset + 1;
603            y_offset += 1;
604            if e >= 0 {
605                e -= 2 * x_offset - 1;
606                x_offset -= 1;
607            }
608        }
609
610        for i in 0..dy {
611            let y = i as isize + (y - r as isize);
612            let x1 = left_buff[i as usize];
613            let x2 = right_buff[i as usize];
614
615            for x in x1..x2 {
616                self.draw_pixel(x, y, color);
617            }
618        }
619    }
620
621    /// Draws a polygon onto the canvas.
622    ///
623    /// # Examples
624    ///
625    /// ```
626    /// use drawing_stuff::canvas::Canvas;
627    /// use drawing_stuff::color::RGBA;
628    ///
629    /// const WIDTH: usize = 1080;
630    /// const HEIGHT: usize = 720;
631    ///
632    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
633    ///
634    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
635    /// let vertices = vec![(200, 100), (500, 700), (300, 800)];
636    /// canvas.draw_polygon(&vertices, color);
637    /// ```
638    pub fn draw_polygon(&mut self, vertices: &Vec<(isize, isize)>, color: RGBA) {
639        if vertices.is_empty() {
640            return;
641        }
642
643        for i in 1..vertices.len() {
644            let (x1, y1) = vertices[i];
645            let (x2, y2) = vertices[i - 1];
646            self.draw_line(x1, y1, x2, y2, color);
647        }
648
649        let (x1, y1) = vertices[0];
650        let (x2, y2) = vertices[vertices.len() - 1];
651        self.draw_line(x1, y1, x2, y2, color);
652    }
653
654    /// Draws a solid polygon onto the canvas.
655    ///
656    /// The vertices of the polygon have to be given in the specified order (clockwise / anti-clockwise).
657    ///
658    /// # Examples
659    ///
660    /// ```
661    /// use drawing_stuff::canvas::Canvas;
662    /// use drawing_stuff::color::RGBA;
663    ///
664    /// const WIDTH: usize = 1080;
665    /// const HEIGHT: usize = 720;
666    ///
667    /// let mut canvas = Canvas::new(WIDTH, HEIGHT);
668    ///
669    /// let color = RGBA { r: 255, g: 255, b: 255, a: 255 };
670    /// let clockwise = true;
671    /// let vertices = vec![(200, 100), (500, 700), (300, 800)]; // clockwise
672    /// canvas.draw_polygon_solid(&vertices, clockwise, color);
673    /// ```
674    pub fn draw_polygon_solid(
675        &mut self,
676        vertices: &Vec<(isize, isize)>,
677        clockwise: bool,
678        color: RGBA,
679    ) {
680        if vertices.is_empty() {
681            return;
682        }
683
684        let mut min_vert = 0;
685        let mut max_vert = 0;
686        for i in 0..vertices.len() {
687            if vertices[i].1 < vertices[min_vert].1 {
688                min_vert = i;
689            }
690            if vertices[i].1 > vertices[max_vert].1 {
691                max_vert = i;
692            }
693        }
694
695        let (start_x, start_y) = vertices[min_vert];
696
697        let vertices = vertices
698            .into_iter()
699            .map(|(x, y)| (x - start_x, y - start_y))
700            .collect::<Vec<_>>();
701
702        let dy = (vertices[max_vert].1 + 1) as usize;
703
704        let mut left_buff = vec![0isize; dy];
705        let mut right_buff = vec![0isize; dy];
706
707        let start_vert = if clockwise { min_vert } else { max_vert };
708        let end_vert = if clockwise { max_vert } else { min_vert };
709
710        let mut vert_index = start_vert;
711        loop {
712            let (x1, y1) = vertices[vert_index % vertices.len()];
713            let (x2, y2) = vertices[(vert_index + 1) % vertices.len()];
714
715            Self::polygon_buffer_line(&mut right_buff, true, x1, y1, x2, y2);
716
717            vert_index += 1;
718            if vert_index % vertices.len() == end_vert {
719                break;
720            }
721        }
722
723        let mut vert_index = end_vert;
724        loop {
725            let (x1, y1) = vertices[vert_index % vertices.len()];
726            let (x2, y2) = vertices[(vert_index + 1) % vertices.len()];
727
728            Self::polygon_buffer_line(&mut left_buff, false, x1, y1, x2, y2);
729
730            vert_index += 1;
731            if vert_index % vertices.len() == start_vert {
732                break;
733            }
734        }
735
736        for i in 0..dy {
737            let y = i as isize + start_y;
738            let x1 = left_buff[i] + start_x;
739            let x2 = right_buff[i] + start_x;
740
741            for x in x1..x2 {
742                self.draw_pixel(x, y, color);
743            }
744        }
745    }
746}
747
748impl Canvas {
749    /// Computes a line for use of drawing solid polygons.
750    fn polygon_buffer_line(
751        buff: &mut Vec<isize>,
752        right: bool,
753        x1: isize,
754        y1: isize,
755        x2: isize,
756        y2: isize,
757    ) {
758        let dx = (x2 - x1).abs();
759        let dy = (y2 - y1).abs();
760
761        let abs_m = dy as f32 / dx as f32;
762        match abs_m <= 1.0 {
763            true => {
764                let (start_x, start_y, end_x, end_y) = if x1 < x2 {
765                    (x1, y1, x2, y2)
766                } else {
767                    (x2, y2, x1, y1)
768                };
769
770                let step = if start_y < end_y { 1 } else { -1 };
771
772                let a = 2 * dy;
773                let b = a - 2 * dx;
774                let mut p = a - dx;
775
776                buff[start_y as usize] = start_x;
777                let mut new_line = false;
778
779                let mut offset = 0isize;
780                for i in 1..=(end_x - start_x) {
781                    match p < 0 {
782                        true => {
783                            p += a;
784                        }
785                        false => {
786                            offset += step;
787                            new_line = true;
788                            p += b;
789                        }
790                    }
791
792                    if right || new_line {
793                        buff[(start_y + offset) as usize] = start_x + i;
794                        new_line = false;
795                    }
796                }
797            }
798            false => {
799                let (start_x, start_y, end_x, end_y) = if y1 < y2 {
800                    (x1, y1, x2, y2)
801                } else {
802                    (x2, y2, x1, y1)
803                };
804
805                let step = if start_x < end_x { 1 } else { -1 };
806
807                let a = 2 * dx;
808                let b = a - 2 * dy;
809                let mut p = a - dy;
810
811                buff[start_y as usize] = start_x;
812
813                let mut offset = 0isize;
814                for i in 1..=(end_y - start_y) {
815                    match p < 0 {
816                        true => {
817                            p += a;
818                        }
819                        false => {
820                            offset += step;
821                            p += b;
822                        }
823                    }
824
825                    buff[(start_y + i) as usize] = start_x + offset;
826                }
827            }
828        }
829    }
830}