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}