old school music tracker
at dev 222 lines 7.5 kB view raw
1use crate::coordinates::FONT_SIZE16; 2 3use super::coordinates::{CharPosition, CharRect, FONT_SIZE, PixelRect, WINDOW_SIZE}; 4use font8x8::UnicodeFonts; 5 6pub struct DrawBuffer { 7 pub framebuffer: Box<[[u8; WINDOW_SIZE.0 as usize]; WINDOW_SIZE.1 as usize]>, 8} 9 10impl Default for DrawBuffer { 11 fn default() -> Self { 12 Self { 13 framebuffer: Box::new([[0; WINDOW_SIZE.0 as usize]; WINDOW_SIZE.1 as usize]), 14 } 15 } 16} 17 18impl DrawBuffer { 19 pub const BACKGROUND_COLOR: u8 = 2; 20 21 pub fn set(&mut self, y: u16, x: u16, color: u8) { 22 self.framebuffer[usize::from(y)][usize::from(x)] = color; 23 } 24 25 pub fn draw_char( 26 &mut self, 27 char_data: [u8; 8], 28 position: CharPosition, 29 fg_color: u8, 30 bg_color: u8, 31 ) { 32 let pixel_pos = PixelRect::from(CharRect::from(position)); 33 let position = (pixel_pos.left(), pixel_pos.top()); 34 for (y, line) in char_data.iter().enumerate() { 35 let y = u16::try_from(y).unwrap(); 36 for x in 0..8 { 37 let color = match (line >> x) & 1 == 1 { 38 true => fg_color, 39 false => bg_color, 40 }; 41 self.set(position.1 + y, position.0 + x, color); 42 } 43 } 44 } 45 46 pub fn draw_string( 47 &mut self, 48 string: &str, 49 position: CharPosition, 50 fg_color: u8, 51 bg_color: u8, 52 ) { 53 for (num, char) in string.char_indices() { 54 self.draw_char( 55 font8x8::BASIC_FONTS.get(char).unwrap(), 56 position + (u8::try_from(num).unwrap(), 0), 57 fg_color, 58 bg_color, 59 ); 60 } 61 } 62 63 /// cuts off the string if it's too long 64 /// if it's too short it gets filled with whitespace 65 pub fn draw_string_length( 66 &mut self, 67 string: &str, 68 position: CharPosition, 69 lenght: u8, 70 fg_color: u8, 71 bg_color: u8, 72 ) { 73 let ulen = usize::from(lenght); 74 if string.len() > ulen { 75 self.draw_string(&string[..=ulen], position, fg_color, bg_color) 76 } else { 77 self.draw_string(string, position, fg_color, bg_color); 78 self.draw_rect( 79 bg_color, 80 CharRect::new( 81 position.y(), 82 position.y(), 83 position.x() + u8::try_from(string.len()).unwrap(), 84 position.x() + lenght, 85 ), 86 ); 87 } 88 } 89 90 /// doesn't draw background. That should be done before calling this function 91 pub fn draw_out_border( 92 &mut self, 93 char_rect: CharRect, 94 top_left_color: u8, 95 bot_right_color: u8, 96 thickness: u8, 97 ) { 98 assert!(thickness <= FONT_SIZE); 99 assert!(thickness > 0); 100 let pixel_rect = PixelRect::from(char_rect); 101 102 let thickness = u16::from(thickness); 103 for x in pixel_rect.left()..=pixel_rect.right() { 104 for y in 0..thickness { 105 self.set(pixel_rect.top() + y, x, top_left_color); 106 self.set(pixel_rect.bot() - y, x, bot_right_color); 107 } 108 } 109 for y in pixel_rect.top()..=pixel_rect.bot() { 110 for x in 0..thickness { 111 self.set(y, pixel_rect.right() - x, bot_right_color); 112 self.set(y, pixel_rect.left() + x, top_left_color); 113 } 114 } 115 } 116 117 pub fn draw_in_box( 118 &mut self, 119 char_rect: CharRect, 120 background_color: u8, 121 top_left_color: u8, 122 bot_right_color: u8, 123 thickness: u8, 124 ) { 125 assert!(thickness < FONT_SIZE); 126 assert!(thickness > 0); 127 let space_from_border = FONT_SIZE16 - u16::from(thickness); 128 129 let pixel_rect = PixelRect::from(char_rect); 130 131 // all pixel lines except those in top and bottom char line 132 for y in (pixel_rect.top() + FONT_SIZE16)..=(pixel_rect.bot() - FONT_SIZE16) { 133 // left side foreground 134 for x in (pixel_rect.left() + space_from_border)..(pixel_rect.left() + FONT_SIZE16) { 135 self.set(y, x, top_left_color); 136 } 137 // left side background 138 for x in pixel_rect.left()..(pixel_rect.left() + space_from_border) { 139 self.set(y, x, background_color); 140 } 141 142 // need the plus ones, as the '..' would need to be exclusive on the low and inclusive on the high, which i dont know how to do 143 for x in 144 (pixel_rect.right() - FONT_SIZE16 + 1)..(pixel_rect.right() - space_from_border + 1) 145 { 146 self.set(y, x, bot_right_color); 147 } 148 // right side background 149 for x in (pixel_rect.right() - space_from_border + 1)..=pixel_rect.right() { 150 self.set(y, x, background_color); 151 } 152 } 153 154 // top char line 155 for y in pixel_rect.top()..(pixel_rect.top() + FONT_SIZE16) { 156 if y < pixel_rect.top() + space_from_border { 157 for x in pixel_rect.horizontal_range() { 158 self.set(y, x, background_color); 159 } 160 } else { 161 for x in pixel_rect.left()..=pixel_rect.right() { 162 let color = if x < pixel_rect.left() + space_from_border 163 || x > pixel_rect.right() - space_from_border 164 { 165 background_color 166 } else if x < pixel_rect.right() 167 - space_from_border 168 - (y - (pixel_rect.top() + space_from_border)) 169 { 170 top_left_color 171 } else { 172 bot_right_color 173 }; 174 175 self.set(y, x, color); 176 } 177 } 178 } 179 180 // bottom char line 181 for y in (pixel_rect.bot() - FONT_SIZE16 + 1)..=pixel_rect.bot() { 182 // does the top 'SPACE_FROM_BORDER' rows in background color 183 if y > pixel_rect.bot() - space_from_border { 184 for x in pixel_rect.horizontal_range() { 185 self.set(y, x, background_color); 186 } 187 } else { 188 for x in pixel_rect.horizontal_range() { 189 let color = if x < pixel_rect.left() + space_from_border 190 || x > pixel_rect.right() - space_from_border 191 { 192 background_color 193 } else if x < pixel_rect.left() + (pixel_rect.bot() - y) { 194 top_left_color 195 } else { 196 bot_right_color 197 }; 198 199 // self.framebuffer[y][x] = color; 200 self.set(y, x, color); 201 } 202 } 203 } 204 } 205 206 pub fn draw_rect(&mut self, color: u8, rect: CharRect) { 207 let pixel_rect = PixelRect::from(rect); 208 self.draw_pixel_rect(color, pixel_rect) 209 } 210 211 pub fn draw_pixel_rect(&mut self, color: u8, rect: PixelRect) { 212 for line in &mut self.framebuffer[usize::from(rect.top())..=usize::from(rect.bot())] { 213 line[usize::from(rect.left())..=usize::from(rect.right())].fill(color); 214 } 215 } 216 217 pub fn show_colors(&mut self) { 218 for i in 0..crate::render::palettes::PALETTE_SIZE as u8 { 219 self.draw_rect(i, CharPosition::new(i, 5).into()); 220 } 221 } 222}