sunshine/
framebuffer.rs

1use std::path::Path;
2use std::io::Write;
3use std::fs::File;
4
5const RGB_WIDTH: usize = 3;
6
7#[derive(Clone, Copy)]
8pub struct RGB {
9    pub r: u8,
10    pub g: u8,
11    pub b: u8,
12    pub a: u8
13}
14
15pub struct Framebuffer {
16    pub height: usize,
17    pub width: usize,
18    pub data: Vec<u8>,
19}
20
21impl Framebuffer {
22    pub fn new(height: usize, width: usize) -> Framebuffer {
23        let size = RGB_WIDTH * width * height;
24        let buffer = vec![0; size as usize];
25        Framebuffer{
26            height: height,
27            width: width,
28            data: buffer,
29        }
30    }
31
32    fn buffer_size(&self) -> usize {
33        RGB_WIDTH * self.height * self.width
34    }
35
36    pub fn clear(&mut self, color: RGB) {
37        let c: Vec<u8> = vec![
38            vec![color.r, color.g, color.b];
39            self.width * self.height
40        ].into_iter().flatten().collect::<Vec<u8>>();
41        self.data = c;
42    }
43
44    fn get_offset(&self, x: usize, y: usize) -> Option<usize> {
45        let offset = (y * self.width * RGB_WIDTH) + (x * RGB_WIDTH);
46        if offset < self.buffer_size() {
47            Some(offset as usize)
48        } else {
49            None
50        }
51    }
52
53    pub fn get_pixel(&self, x: usize, y: usize) -> Option<RGB> {
54        match self.get_offset(x, y) {
55            Some(offset) => {
56                let r = self.data[offset];
57                let g = self.data[offset + 1];
58                let b = self.data[offset + 2];
59                Some(RGB {r: r, g: g, b: b, a: 255})
60            },
61            None => None
62        }
63    }
64
65    pub fn set_pixel(&mut self, x: usize, y: usize, color: RGB) -> bool {
66        match self.get_offset(x, y) {
67            Some(offset) => {
68                self.data[offset] = color.r;
69                self.data[offset + 1] = color.g;
70                self.data[offset + 2] = color.b;
71                true
72            },
73            None => false
74        }
75    }
76
77    pub fn draw_rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: RGB) -> bool {
78        let mut success = true;
79        while success {
80            for i in 0..w {
81                for j in 0..h {
82                    let cx = x + i;
83                    let cy = y + j;
84                    if cx >= self.width || cy >= self.height {
85                        continue
86                    }
87                    success = self.set_pixel(cx, cy, color);
88                }
89            }
90            break
91        }
92        success
93    }
94
95    pub fn write_file(&self, filename: &str) -> std::io::Result<()> {
96        let path = Path::new(filename);
97        let mut file = File::create(&path)?;
98        let header = format!("P6 {} {} 255\n", self.width, self.height);
99        file.write(header.as_bytes())?;
100        file.write(&self.data)?;
101        Ok(())
102    }
103}