embedded_gfx/
draw.rs

1use embedded_graphics_core::draw_target::DrawTarget;
2use embedded_graphics_core::prelude::Point;
3
4use crate::DrawPrimitive;
5
6#[inline]
7pub fn draw<D: DrawTarget<Color = embedded_graphics_core::pixelcolor::Rgb565>>(
8    primitive: DrawPrimitive,
9    fb: &mut D,
10) where
11    <D as DrawTarget>::Error: std::fmt::Debug,
12{
13    match primitive {
14        DrawPrimitive::Line(p1, p2, color) => {
15            fb.draw_iter(
16                line_drawing::Bresenham::new((p1.x, p1.y), (p2.x, p2.y))
17                    .map(|(x, y)| embedded_graphics_core::Pixel(Point::new(x, y), color)),
18            )
19            .unwrap();
20        }
21        DrawPrimitive::ColoredPoint(p, c) => {
22            let p = embedded_graphics_core::geometry::Point::new(p.x, p.y);
23
24            fb.draw_iter([embedded_graphics_core::Pixel(p, c)]).unwrap();
25        }
26        DrawPrimitive::ColoredTriangle(p1, p2, p3, color) => {
27            //sort vertices by y
28            let mut vertices = [p1, p2, p3];
29            vertices.sort_by(|a, b| a.y.cmp(&b.y));
30
31            let [p1, p2, p3] = vertices
32                .iter()
33                .map(|p| embedded_graphics_core::geometry::Point::new(p.x, p.y))
34                .collect::<Vec<embedded_graphics_core::geometry::Point>>()
35                .try_into()
36                .unwrap();
37
38            if p2.y == p3.y {
39                fill_bottom_flat_triangle(p1, p2, p3, color, fb);
40            } else if p1.y == p2.y {
41                fill_top_flat_triangle(p1, p2, p3, color, fb);
42            } else {
43                let p4 = Point::new(
44                    (p1.x as f32
45                        + ((p2.y - p1.y) as f32 / (p3.y - p1.y) as f32) * (p3.x - p1.x) as f32)
46                        as i32,
47                    p2.y,
48                );
49
50                fill_bottom_flat_triangle(p1, p2, p4, color, fb);
51                fill_top_flat_triangle(p2, p4, p3, color, fb);
52            }
53        }
54    }
55}
56
57fn fill_bottom_flat_triangle<D: DrawTarget<Color = embedded_graphics_core::pixelcolor::Rgb565>>(
58    p1: Point,
59    p2: Point,
60    p3: Point,
61    color: embedded_graphics_core::pixelcolor::Rgb565,
62    fb: &mut D,
63) where
64    <D as DrawTarget>::Error: std::fmt::Debug,
65{
66    let invslope1 = (p2.x - p1.x) as f32 / (p2.y - p1.y) as f32;
67    let invslope2 = (p3.x - p1.x) as f32 / (p3.y - p1.y) as f32;
68
69    let mut curx1 = p1.x as f32;
70    let mut curx2 = p1.x as f32;
71
72    for scanline_y in p1.y..=p2.y {
73        draw_horizontal_line(
74            Point::new(curx1 as i32, scanline_y),
75            Point::new(curx2 as i32, scanline_y),
76            color,
77            fb,
78        );
79
80        curx1 += invslope1;
81        curx2 += invslope2;
82    }
83}
84
85fn fill_top_flat_triangle<D: DrawTarget<Color = embedded_graphics_core::pixelcolor::Rgb565>>(
86    p1: Point,
87    p2: Point,
88    p3: Point,
89    color: embedded_graphics_core::pixelcolor::Rgb565,
90    fb: &mut D,
91) where
92    <D as DrawTarget>::Error: std::fmt::Debug,
93{
94    let invslope1 = (p3.x - p1.x) as f32 / (p3.y - p1.y) as f32;
95    let invslope2 = (p3.x - p2.x) as f32 / (p3.y - p2.y) as f32;
96
97    let mut curx1 = p3.x as f32;
98    let mut curx2 = p3.x as f32;
99
100    for scanline_y in (p1.y..=p3.y).rev() {
101        draw_horizontal_line(
102            Point::new(curx1 as i32, scanline_y),
103            Point::new(curx2 as i32, scanline_y),
104            color,
105            fb,
106        );
107
108        curx1 -= invslope1;
109        curx2 -= invslope2;
110    }
111}
112
113fn draw_horizontal_line<D: DrawTarget<Color = embedded_graphics_core::pixelcolor::Rgb565>>(
114    p1: Point,
115    p2: Point,
116    color: embedded_graphics_core::pixelcolor::Rgb565,
117    fb: &mut D,
118) where
119    <D as DrawTarget>::Error: std::fmt::Debug,
120{
121    let start = p1.x.min(p2.x);
122    let end = p1.x.max(p2.x);
123
124    for x in start..=end {
125        fb.draw_iter([embedded_graphics_core::Pixel(Point::new(x, p1.y), color)])
126            .unwrap();
127    }
128}