Skip to main content

pixelab_rgb8888x4/
lib.rs

1use pixelab_core::{Area, Bitmap, BitmapFormat, Color, PixelabError, Point};
2
3pub struct RGB8888x4 {
4    bitmap: BitmapFormat,
5    area: Area,
6}
7impl RGB8888x4 {
8    pub fn new(area: Area) -> Box<Self> {
9        let buffer = vec![0; area.width as usize * area.height as usize * 4];
10        Box::new(Self {
11            bitmap: BitmapFormat::RGB8888x4(buffer),
12            area,
13        })
14    }
15}
16impl Bitmap for RGB8888x4 {
17    fn create(&self, area: Area) -> Box<dyn Bitmap + 'static> {
18        let buffer = vec![0; area.width as usize * area.height as usize * 4];
19        Box::new(Self {
20            bitmap: BitmapFormat::RGB8888x4(buffer),
21            area,
22        })
23    }
24
25    fn set_pixel(&mut self, point: Point, color: Color) -> Result<(), PixelabError> {
26        if point.x >= self.area.width || point.y >= self.area.height {
27            Err(PixelabError::PointOutOfBounds {
28                point,
29                bound: self.area,
30            })
31        } else {
32            match &mut self.bitmap {
33                BitmapFormat::RGB8888x4(buffer) => {
34                    let offset =
35                        ((point.y as u32 * self.area.width as u32 + point.x as u32) * 4) as usize;
36                    buffer[offset] = color.red;
37                    buffer[offset + 1] = color.green;
38                    buffer[offset + 2] = color.blue;
39                    buffer[offset + 3] = color.alpha;
40                    Ok(())
41                }
42                _ => Err(PixelabError::BitmapFormatMismatch),
43            }
44        }
45    }
46
47    fn fill(&mut self, color: Color) -> Result<(), PixelabError> {
48        match &mut self.bitmap {
49            BitmapFormat::RGB8888x4(buffer) => {
50                let pattern = [color.blue, color.green, color.red, color.alpha];
51                let repeated = pattern.repeat(self.area.width as usize * self.area.height as usize);
52                buffer.copy_from_slice(&repeated);
53                Ok(())
54            }
55            _ => Err(PixelabError::BitmapFormatMismatch),
56        }
57    }
58
59    fn overlay(
60        &mut self,
61        fb: &mut Box<dyn Bitmap + 'static>,
62        point: Point,
63    ) -> Result<(), PixelabError> {
64        if fb.area().width + point.x > self.area.width
65            || fb.area().height + point.y > self.area.height
66        {
67            return Err(PixelabError::BitmapOutOfBounds {
68                point,
69                main_bound: self.area,
70                sub_bound: fb.area().clone(),
71            });
72        }
73        let start_x = point.x.max(0) as usize;
74        let start_y = point.y.max(0) as usize;
75        let end_x = (point.x + fb.area().width).min(self.area.width) as usize;
76        let end_y = (point.y + fb.area().height).min(self.area.height) as usize;
77        let width = fb.area().width as usize;
78        let big_fb = match fb.buffer() {
79            BitmapFormat::RGB8888x4(buffer) => buffer,
80            _ => return Err(PixelabError::BitmapFormatMismatch),
81        };
82        match &mut self.bitmap {
83            BitmapFormat::RGB8888x4(buffer) => {
84                for y in start_y..end_y {
85                    let dst_start = (y * self.area.width as usize + start_x) * 4;
86                    let src_start = ((y - start_y) * width + (start_x - point.x as usize)) * 4;
87                    let row_width = (end_x - start_x) * 4;
88                    unsafe {
89                        core::ptr::copy_nonoverlapping(
90                            big_fb[src_start..].as_ptr(),
91                            buffer[dst_start..].as_mut_ptr(),
92                            row_width,
93                        );
94                    }
95                }
96            }
97            _ => return Err(PixelabError::BitmapFormatMismatch),
98        };
99        Ok(())
100    }
101
102    fn buffer(&mut self) -> &mut BitmapFormat {
103        &mut self.bitmap
104    }
105
106    fn area(&mut self) -> &mut Area {
107        &mut self.area
108    }
109}