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}