Skip to main content

altui_core/widgets/canvas/
line.rs

1use crate::{
2    style::Color,
3    widgets::canvas::{Painter, Shape},
4};
5
6/// Shape to draw a line from (x1, y1) to (x2, y2) with the given color
7#[derive(Debug, Clone)]
8pub struct Line {
9    pub x1: f64,
10    pub y1: f64,
11    pub x2: f64,
12    pub y2: f64,
13    pub color: Color,
14}
15
16impl Shape for Line {
17    fn draw(&self, painter: &mut Painter) {
18        let (x1, y1) = match painter.get_point(self.x1, self.y1) {
19            Some(c) => c,
20            None => return,
21        };
22        let (x2, y2) = match painter.get_point(self.x2, self.y2) {
23            Some(c) => c,
24            None => return,
25        };
26        let (dx, x_range) = if x2 >= x1 {
27            (x2 - x1, x1..=x2)
28        } else {
29            (x1 - x2, x2..=x1)
30        };
31        let (dy, y_range) = if y2 >= y1 {
32            (y2 - y1, y1..=y2)
33        } else {
34            (y1 - y2, y2..=y1)
35        };
36
37        if dx == 0 {
38            for y in y_range {
39                painter.paint(x1, y, self.color);
40            }
41        } else if dy == 0 {
42            for x in x_range {
43                painter.paint(x, y1, self.color);
44            }
45        } else if dy < dx {
46            if x1 > x2 {
47                draw_line_low(painter, x2, y2, x1, y1, self.color);
48            } else {
49                draw_line_low(painter, x1, y1, x2, y2, self.color);
50            }
51        } else if y1 > y2 {
52            draw_line_high(painter, x2, y2, x1, y1, self.color);
53        } else {
54            draw_line_high(painter, x1, y1, x2, y2, self.color);
55        }
56    }
57}
58
59fn draw_line_low(painter: &mut Painter, x1: usize, y1: usize, x2: usize, y2: usize, color: Color) {
60    let dx = (x2 - x1) as isize;
61    let dy = (y2 as isize - y1 as isize).abs();
62    let mut d = 2 * dy - dx;
63    let mut y = y1;
64    for x in x1..=x2 {
65        painter.paint(x, y, color);
66        if d > 0 {
67            y = if y1 > y2 {
68                y.saturating_sub(1)
69            } else {
70                y.saturating_add(1)
71            };
72            d -= 2 * dx;
73        }
74        d += 2 * dy;
75    }
76}
77
78fn draw_line_high(painter: &mut Painter, x1: usize, y1: usize, x2: usize, y2: usize, color: Color) {
79    let dx = (x2 as isize - x1 as isize).abs();
80    let dy = (y2 - y1) as isize;
81    let mut d = 2 * dx - dy;
82    let mut x = x1;
83    for y in y1..=y2 {
84        painter.paint(x, y, color);
85        if d > 0 {
86            x = if x1 > x2 {
87                x.saturating_sub(1)
88            } else {
89                x.saturating_add(1)
90            };
91            d -= 2 * dy;
92        }
93        d += 2 * dx;
94    }
95}