1use framebuffer::Framebuffer;
2use framebuffer::KdMode;
3use framebuffer::FramebufferError;
4use std::ops::Add;
5use std::ops::AddAssign;
6
7pub struct Pixel {
9 index: usize,
10}
11
12impl Pixel {
13 pub fn set_rgb(&self, buffer: &mut [u8], r: u8, g: u8, b: u8) {
15 buffer[self.index]=b;
16 buffer[self.index+1]=g;
17 buffer[self.index+2]=r;
18 }
19 pub fn get_rgb(&self, buffer: &[u8]) -> (u8,u8,u8) {
21 (buffer[self.index+2], buffer[self.index+1], buffer[self.index])
22 }
23}
24
25#[derive(Clone,Copy)]
27pub struct Point {
28 pub x: usize,
29 pub y: usize,
30}
31
32impl Point{
33 pub fn new(x: usize, y: usize) -> Self {
35 Point{x,y}
36 }
37}
38
39impl Add<(usize,usize)> for Point {
40 type Output = Self;
41
42 fn add(self, offset: (usize, usize)) -> Self {
55 Self {
56 x: self.x + offset.0,
57 y: self.y + offset.1,
58 }
59 }
60}
61
62impl AddAssign<(usize,usize)> for Point {
63 fn add_assign(&mut self, offset: (usize, usize)){
64 self.x += offset.0;
65 self.y += offset.1;
66 }
67}
68
69impl From<(usize,usize)> for Point {
70 fn from(p: (usize, usize)) -> Self {
71 Point {x: p.0, y: p.1}
72 }
73}
74
75pub struct Rectangle {
76 pub location: Point,
77 pub height: usize,
78 pub width: usize,
79 pub pixels: Vec<Vec<Pixel>>,
80}
81
82impl Rectangle {
83 fn from_dimensions(loc: &Point, height: usize, width: usize, fb : &Framebuffer) -> Self {
85 let line_length = fb.fix_screen_info.line_length as usize;
86 let bytespp = (fb.var_screen_info.bits_per_pixel / 8) as usize;
87 let mut rows = Vec::new();
88 for i in 0..height {
89 let mut pixel_line = Vec::new();
90 for k in 0..width {
91 let index = ((i + loc.y) * line_length + (k + loc.x) * bytespp) as usize;
92 pixel_line.push(Pixel{index});
93 }
94 rows.push(pixel_line);
95 }
96 Rectangle {
97 location: *loc,
98 height,
99 width,
100 pixels: rows,
101 }
102 }
103 fn fill(&self, buffer: &mut [u8], rgb: (u8,u8,u8)) {
105 for row in self.pixels.iter() {
106 for p in row.iter() {
107 p.set_rgb(buffer, rgb.0, rgb.1, rgb.2);
108 }
109 }
110
111 }
112}
113
114pub struct Border {
116 pub top: Rectangle,
117 pub bot: Rectangle,
118 pub left: Rectangle,
119 pub right: Rectangle,
120}
121
122pub struct Window {
124 pub border: Option<Border>,
125 pub width: usize,
126 pub height: usize,
127 pub main_context: Rectangle,
128}
129
130impl Window {
131 fn fill(&self, buffer: &mut [u8], rgb: (u8,u8,u8)) {
133 self.main_context.fill(buffer,rgb);
134 }
135 fn fill_border(&self, buffer: &mut [u8], rgb: (u8,u8,u8)) {
137 match &self.border {
138 Some(br) => {
139 br.top.fill(buffer, rgb);
140 br.left.fill(buffer, rgb);
141 br.right.fill(buffer, rgb);
142 br.bot.fill(buffer, rgb);
143 },
144 _ => {}
145 }
146 }
147}
148
149pub struct WindowTemplate {
151 pub id: usize,
152 pub location: Point,
153 pub width: usize,
154 pub height: usize,
155 pub border_thickness: usize,
156}
157
158pub struct FBmanager {
160 pub framebuffer: Framebuffer,
161 pub buffer: Vec<u8>,
162 pub windows: Vec<Window>,
163}
164
165impl FBmanager {
166 pub fn new(template: &[WindowTemplate]) -> Self {
168 let framebuffer = Framebuffer::new("/dev/fb0").unwrap();
169 let height = framebuffer.var_screen_info.yres;
170 let line_length = framebuffer.fix_screen_info.line_length;
171 let buffer = vec![0u8; (line_length*height) as usize];
172 let mut window_holder = Vec::new();
173 for t in template.iter() {
174 let mut border = None;
176 let mut start_location = t.location;
177 let mut context_height = t.height;
178 let mut context_width = t.width;
179 if t.border_thickness > 0 {
180 let border_height = t.border_thickness;
182 let border_width = t.width;
183 let top = Rectangle::from_dimensions(&t.location,border_height, border_width, &framebuffer);
184 let loc = t.location + (0, t.height - t.border_thickness);
186 let bot = Rectangle::from_dimensions(&loc, border_height, border_width, &framebuffer);
187 let loc = t.location + (t.width - t.border_thickness, t.border_thickness);
189 let border_height = t.height - 2*t.border_thickness;
190 let border_width = t.border_thickness;
191 let right = Rectangle::from_dimensions(&loc, border_height, border_width, &framebuffer);
192 let loc = t.location + (0, t.border_thickness);
194 let left = Rectangle::from_dimensions(&loc, border_height, border_width, &framebuffer);
195 border = Some(Border {
196 top,
197 bot,
198 left,
199 right,
200 });
201
202 start_location += (t.border_thickness, t.border_thickness);
203 context_height -= 2*t.border_thickness;
204 context_width -= 2*t.border_thickness;
205 }
206 let main_context = Rectangle::from_dimensions(&start_location, context_height, context_width, &framebuffer);
208 let window = Window {
209 border,
210 width: t.width,
211 height: t.height,
212 main_context,
213 };
214 window_holder.push(window);
215 }
216 FBmanager {
217 framebuffer,
218 buffer,
219 windows: window_holder,
220 }
221 }
222 pub fn enable_graphics() -> Result<i32, FramebufferError> {
225 Framebuffer::set_kd_mode(KdMode::Graphics)
226 }
227 pub fn disable_graphics() -> Result<i32, FramebufferError> {
229 Framebuffer::set_kd_mode(KdMode::Text)
230 }
231 pub fn fill(&mut self, id: usize, rgb: (u8,u8,u8)) {
233 self.windows[id].fill(&mut self.buffer, rgb);
234 }
235 pub fn fill_border(&mut self, id: usize, rgb: (u8,u8,u8)) {
237 self.windows[id].fill_border(&mut self.buffer, rgb);
238 }
239 pub fn draw(&mut self) {
241 self.framebuffer.write_frame( &self.buffer);
242 }
243}
244
245#[cfg(test)]
248mod tests {
249 use super::*;
250
251 #[test]
252 fn single_square() {
253 let square = WindowTemplate {
254 id: 0,
255 location: Point::new(0,0),
256 width: 1000,
257 height: 1000,
258 border_thickness: 0,
259 };
260 let mut fm = FBmanager::new(&[square]);
261 let mut win = &mut fm.windows[0];
262 fm.windows[0].main_context.pixels[0][0].set_rgb(&mut fm.buffer,255,0,0);
263 fm.fill(0,(255,0,0));
264 let step_size = (fm.framebuffer.var_screen_info.bits_per_pixel / 8) as usize;
265 let line_length: usize = fm.framebuffer.fix_screen_info.line_length as usize;
266 println!("{:?}", fm.buffer);
267 for i in 0..1000 {
268 for q in 0..1000 {
269 let index: usize = i*line_length + q*step_size;
270 assert_eq!(fm.buffer[index], 0);
271 assert_eq!(fm.buffer[index+1], 0);
272 assert_eq!(fm.buffer[index+2], 255);
273 }
274 }
275 }
276}