1
2use image::{ DynamicImage, GenericImageView };
3
4pub struct DrawBuffer {
9 width: u32,
10 height: u32,
11 data: Vec<u32>,
12 scale: f32,
13}
14
15impl DrawBuffer {
16 pub fn new( w: u32, h: u32 ) -> DrawBuffer {
17 DrawBuffer {
18 width: w,
19 height: h,
20 data: vec![0; ( w*h ) as usize],
21 scale: 1.0,
22 }
23 }
24
25 pub fn get_scale( &self ) -> f32 {
26 self.scale
27 }
28 pub fn set_scale( &mut self, scale: f32 ) {
29 self.scale = scale;
30 }
31
32 pub fn copy_from_draw_buffer( &mut self, other: &DrawBuffer ) {
33 self.data.copy_from_slice( other.get_data() );
35 }
36
37 pub fn fill_with_grid( &mut self, size: u32, col_a: u32, col_b: u32 ) {
38 let h = self.height; let w = self.width; let mut pos = 0;
41 for y in 0..h {
42 for x in 0..w {
43 if ( x/size + y/size )%2 == 0 {
44 self.data[ pos ] = col_a;
45 } else {
46 self.data[ pos ] = col_b;
47 }
48 pos += 1;
49 }
50 }
51 }
52
53 pub fn blit_image( &mut self, image: &DynamicImage) {
54 let mut pos = 0;
55 let h = self.height;
56 let w = self.width;
57 for y in 0..h {
58 for x in 0..w {
59 let sx = ( x as f32 * self.scale ).trunc() as u32;
60 let sy = ( y as f32 * self.scale ).trunc() as u32;
61 let pixel = image.get_pixel( sx, sy );
62 let r = pixel[ 0 ] as u32;
63 let g = pixel[ 1 ] as u32;
64 let b = pixel[ 2 ] as u32;
65 let a = pixel[ 3 ] as u32;
66 let bg = self.data[ pos ];
67 let fg: u32 = ( r << 16 )|( g << 8 )|( b << 0 );
68 let rgb = DrawBuffer::mix_rgba( fg, bg, ( a as f32 )/255.0 );
69
70 self.data[ pos ] = rgb;
71 pos += 1;
72 }
73 }
74 }
75
76 pub fn draw_hline( &mut self, sx: u32, ex: u32, y: u32, col: u32 ) {
77 let w = self.width as usize;
80 let h = self.height as usize;
81
82 let mut y = ( y as f32 / self.scale ) as usize;
83 let mut sx = ( sx as f32 / self.scale ) as usize;
84 let mut ex = ( ex as f32 / self.scale ) as usize;
85 if y >= h {
86 y = h-1;
87 }
88 if sx >= w {
89 sx = w-1;
90 }
91 if ex >= w {
92 ex = w-1;
93 }
94 let col = col >> 8; for x in sx..=ex {
96 let p = w * y + x;
97 self.data[ p ] = col;
98 }
99 }
100
101 #[allow(dead_code)]
102 fn draw_vline( &mut self, x: u32, sy: u32, ey: u32, col: u32 ) {
103 let w = self.width as usize;
105 let h = self.height as usize;
106
107 let mut x = ( x as f32 / self.scale ) as usize;
108 let mut sy = ( sy as f32 / self.scale ) as usize;
109 let mut ey = ( ey as f32 / self.scale ) as usize;
110 if x >= w {
111 x = w-1;
112 }
113 if sy >= h {
114 sy = h-1;
115 }
116 if ey >= h {
117 ey = h-1;
118 }
119 let col = col >> 8; for y in sy..=ey {
121 let p = w * y + x;
122 self.data[ p ] = col;
123 }
124 }
125
126 fn clamp_i32( v: i32, min: i32, max: i32 ) -> i32 {
127 if v < min {
128 min
129 } else if v > max {
130 max
131 } else {
132 v
133 }
134 }
135
136 pub fn draw_filled_rectangle( &mut self, sx: i32, sy: i32, ex: i32, ey: i32, col: u32 ) {
137 let s = self.scale;
140 let sx = ( ( sx as f32 )/s ).trunc() as i32;
141 let sy = ( ( sy as f32 )/s ).trunc() as i32;
142 let ex = ( ( ex as f32 )/s ).trunc() as i32;
143 let ey = ( ( ey as f32 )/s ).trunc() as i32;
144
145 let sx = DrawBuffer::clamp_i32( sx, 0, self.width as i32 ) as u32;
146 let sy = DrawBuffer::clamp_i32( sy, 0, self.height as i32 ) as u32;
147 let ex = DrawBuffer::clamp_i32( ex, 0, self.width as i32 ) as u32;
148 let ey = DrawBuffer::clamp_i32( ey, 0, self.height as i32 ) as u32;
149
150for y in sy..ey {
152 for x in sx..ex {
153 let offset = ( self.width * y + x ) as usize;
154 self.data[ offset ] = col;
155 }
156 }
157 }
158 pub fn draw_frame( &mut self, x: i32, y: i32, fw: u32, fh: u32, col: u32, line_width: u32 ) {
159 let hw = ( ( line_width as f32 )*0.5 ).trunc() as i32;
160 let fw = fw as i32;
161 let fh = fh as i32;
162
163 self.draw_filled_rectangle( x-hw, y-hw, x+fw+hw, y+hw, col );
165 self.draw_filled_rectangle( x-hw, y+fh-hw, x+fw+hw, y+fh+hw, col );
167 self.draw_filled_rectangle( x-hw, y+hw, x+hw, y+fh-hw, col );
169 self.draw_filled_rectangle( x+fw-hw, y+hw, x+fw+hw, y+fh-hw, col );
171 }
172
173 pub fn get_width( &self ) -> u32 {
174 self.width
175 }
176 pub fn get_height( &self ) -> u32 {
177 self.height
178 }
179
180 pub fn get_data( &self ) -> &Vec<u32> {
181 &self.data
182 }
183
184 pub fn mix_rgba( a: u32, b: u32, f: f32 ) -> u32 {
186 let ra = ( ( a >> 24 )&0x000000ff ) as u8;
187 let ga = ( ( a >> 16 )&0x000000ff ) as u8;
188 let ba = ( ( a >> 8 )&0x000000ff ) as u8;
189 let aa = ( ( a >> 0 )&0x000000ff ) as u8;
190
191 let rb = ( ( b >> 24 )&0x000000ff ) as u8;
192 let gb = ( ( b >> 16 )&0x000000ff ) as u8;
193 let bb = ( ( b >> 8 )&0x000000ff ) as u8;
194 let ab = ( ( b >> 0 )&0x000000ff ) as u8;
195
196 let r = ( ( ra as f32 ) * f + ( rb as f32 ) * ( 1.0 -f ) ) as u32;
197 let g = ( ( ga as f32 ) * f + ( gb as f32 ) * ( 1.0 -f ) ) as u32;
198 let b = ( ( ba as f32 ) * f + ( bb as f32 ) * ( 1.0 -f ) ) as u32;
199 let a = ( ( aa as f32 ) * f + ( ab as f32 ) * ( 1.0 -f ) ) as u32;
200
201 let rgba = ( r << 24 )|( g << 16 )|( b << 8 )|a;
202
203 rgba
204 }
205
206 #[allow(dead_code)]
207 fn mix_byte( a: u8, b: u8, f: u8 ) -> u8 {
208 let f = ( f as f32 )/255.0;
209 let fa = a as f32 * f;
210 let fb = b as f32 * (1.0-f);
211
212 ( fa + fb ) as u8
213 }
214
215}