1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![warn(missing_docs)]
extern crate line_drawing;
extern crate rusttype;
extern crate walkdir;
extern crate xdg;
extern crate xml;
#[macro_use]
extern crate bitflags;
pub mod line;
pub mod shapes;
pub mod text;
pub trait Drawable {
fn draw(&self, canvas: &mut Canvas);
}
#[derive(Debug, PartialEq)]
pub enum Endian {
Little,
Big,
}
impl Endian {
pub fn native() -> Endian {
if cfg!(target_endian = "little") {
Endian::Little
} else {
Endian::Big
}
}
}
pub struct Canvas<'a> {
pub buffer: &'a mut [u8],
pub width: usize,
pub height: usize,
pub stride: usize,
pub pixel_size: usize,
pub endianness: Endian,
}
impl<'a> Canvas<'a> {
pub fn new(
buffer: &'a mut [u8],
width: usize,
height: usize,
stride: usize,
endianness: Endian,
) -> Canvas<'a> {
assert!(
stride % width == 0,
"Incorrect Dimensions - Stride is not a multiple of width"
);
assert!(buffer.len() == stride * height);
let pixel_size = stride / width;
Canvas {
buffer,
width,
height,
stride,
pixel_size,
endianness,
}
}
pub fn draw<D: Drawable>(&mut self, drawable: &D) {
drawable.draw(self);
}
pub fn draw_point(&mut self, x: usize, y: usize, color: [u8; 4]) {
let base = self.stride * y + self.pixel_size * x;
if self.endianness == Endian::Little {
if color[0] == 255 {
self.buffer[base + 3] = color[0];
self.buffer[base + 2] = color[1];
self.buffer[base + 1] = color[2];
self.buffer[base] = color[3];
} else {
for c in 0..3 {
let alpha = f32::from(color[0]) / 255.0;
let color_diff =
(color[3 - c] as isize - self.buffer[base + c] as isize) as f32 * alpha;
let new_color = (f32::from(self.buffer[base + c]) + color_diff) as u8;
self.buffer[base + c] = new_color as u8;
}
self.buffer[base + 3] = 255 as u8;
}
} else if color[0] == 255 {
self.buffer[base] = color[0];
self.buffer[base + 1] = color[1];
self.buffer[base + 2] = color[2];
self.buffer[base + 3] = color[3];
} else {
for c in 1..4 {
let alpha = f32::from(color[0]) / 255.0;
let color_diff =
(color[c] as isize - self.buffer[base + c] as isize) as f32 * alpha;
let new_color = (f32::from(self.buffer[base + c]) + color_diff) as u8;
self.buffer[base + c] = new_color as u8;
}
self.buffer[base] = 255 as u8;
}
}
pub fn clear(&mut self) {
for i in 0..self.width * self.height * 4 {
self.buffer[i] = 0x00;
}
}
}