Skip to main content

winit_ui/
canvas.rs

1pub struct Canvas<'a> {
2    frame: &'a mut [u8],
3    pub width: u32,
4    pub height: u32,
5}
6
7impl<'a> Canvas<'a> {
8    pub(crate) fn new(frame: &'a mut [u8], width: u32, height: u32) -> Self {
9        Self { frame, width, height }
10    }
11
12    fn idx(&self, x: u32, y: u32) -> usize {
13        ((y * self.width + x) * 4) as usize
14    }
15
16    pub fn set_pixel(&mut self, x: u32, y: u32, color: &crate::color::Color) {
17        if x >= self.width || y >= self.height { return; }
18        let i = self.idx(x, y);
19        self.frame[i]     = color.r;
20        self.frame[i + 1] = color.g;
21        self.frame[i + 2] = color.b;
22        self.frame[i + 3] = color.a;
23    }
24
25    pub fn clear(&mut self, color: crate::color::Color) {
26        for pixel in self.frame.chunks_exact_mut(4) {
27            pixel[0] = color.r;
28            pixel[1] = color.g;
29            pixel[2] = color.b;
30            pixel[3] = color.a;
31        }
32    }
33
34    pub fn draw_rect_f(&mut self, x: u32, y: u32, w: u32, h: u32, color: &crate::color::Color) {
35        for row in y..(y + h) {
36            for col in x..(x + w) {
37                self.set_pixel(col, row, color);
38            }
39        }
40    }
41
42    pub fn draw_rect(&mut self, x: u32, y: u32, w: u32, h: u32, color: &crate::color::Color) {
43        for col in x..(x + w) {
44            self.set_pixel(col, y, color);
45            self.set_pixel(col, y + h - 1, color);
46        }
47        for row in y..(y + h) {
48            self.set_pixel(x, row, color);
49            self.set_pixel(x + w - 1, row, color);
50        }
51    }
52
53    pub fn draw_line(&mut self, x0: u32, y0: u32, x1: u32, y1: u32, color: &crate::color::Color) {
54        let mut x0 = x0 as i32;
55        let mut y0 = y0 as i32;
56        let x1 = x1 as i32;
57        let y1 = y1 as i32;
58
59        let dx = (x1 - x0).abs();
60        let dy = -(y1 - y0).abs();
61        let sx = if x0 < x1 { 1 } else { -1 };
62        let sy = if y0 < y1 { 1 } else { -1 };
63        let mut err = dx + dy;
64
65        loop {
66            self.set_pixel(x0 as u32, y0 as u32, &color);
67            if x0 == x1 && y0 == y1 { break; }
68            let e2 = 2 * err;
69            if e2 >= dy { err += dy; x0 += sx; }
70            if e2 <= dx { err += dx; y0 += sy; }
71        }
72    }
73
74    pub fn draw_circle_f(&mut self, cx: u32, cy: u32, radius: u32, color: &crate::color::Color) {
75        let cx = cx as i32;
76        let cy = cy as i32;
77        let radius = radius as i32;
78
79        for y in (cy - radius)..=(cy + radius) {
80            for x in (cx - radius)..=(cx + radius) {
81                let dx = x - cx;
82                let dy = y - cy;
83                if dx * dx + dy * dy <= radius * radius {
84                    if x >= 0 && y >= 0 {
85                        self.set_pixel(x as u32, y as u32, color);
86                    }
87                }
88            }
89        }
90    }
91
92    pub fn draw_circle(&mut self, cx: u32, cy: u32, radius: u32, color: &crate::color::Color) {
93        let cx = cx as i32;
94        let cy = cy as i32;
95        let radius = radius as i32;
96
97        let mut x = radius;
98        let mut y = 0;
99        let mut err = 0;
100
101        while x >= y {
102            self.set_pixel((cx + x) as u32, (cy + y) as u32, color);
103            self.set_pixel((cx + y) as u32, (cy + x) as u32, color);
104            self.set_pixel((cx - y) as u32, (cy + x) as u32, color);
105            self.set_pixel((cx - x) as u32, (cy + y) as u32, color);
106            self.set_pixel((cx - x) as u32, (cy - y) as u32, color);
107            self.set_pixel((cx - y) as u32, (cy - x) as u32, color);
108            self.set_pixel((cx + y) as u32, (cy - x) as u32, color);
109            self.set_pixel((cx + x) as u32, (cy - y) as u32, color);
110
111            if err <= 0 {
112                y += 1;
113                err += 2 * y + 1;
114            }
115            if err > 0 {
116                x -= 1;
117                err -= 2 * x + 1;
118            }
119        }
120    }
121
122    pub fn draw_text(&mut self, mut x: u32, y: u32, size: f32, text: &str, font: &crate::font::Font, color: &crate::color::Color) {
123        for char in text.chars() {
124            if char.is_ascii() {
125                let (metrics, glyph) = font.rasterize(char, size);
126                for gx in 0..metrics.width {
127                    for gy in 0..metrics.height {
128                        let alpha = glyph[gy * metrics.width + gx];
129                        let blended_color = crate::color::Color {
130                            r: ((color.r as u16 * alpha as u16) / 255) as u8,
131                            g: ((color.g as u16 * alpha as u16) / 255) as u8,
132                            b: ((color.b as u16 * alpha as u16) / 255) as u8,
133                            a: alpha,
134                        };
135                        let px = (x as i32 + gx as i32 + metrics.xmin) as u32;
136                        let py = (y as i32 - metrics.height as i32 + gy as i32 - metrics.ymin) as u32;
137                        self.set_pixel(px, py, &blended_color);
138                    }
139                }
140                x += metrics.advance_width as u32;
141            }
142        }
143    }
144}