type-render
korin 3 years ago
parent 75f315c646
commit 4791b3cfb9
  1. 44
      src/font_build.rs
  2. 214
      src/main.rs

@ -30,8 +30,6 @@ fn read_file(file_name: String) -> Vec<u8> {
pub fn generate_glyph_atlas() -> Vec<Glyph> {
// Retrieve font data from file
let file_path = String::from("./fonts/Terminus14x8.data");
println!("In file {file_path}");
let contents = read_file(file_path);
// Get width of image for proper positioning of pixels
@ -39,9 +37,9 @@ pub fn generate_glyph_atlas() -> Vec<Glyph> {
let width_right_byte = contents[1];
let number = [width_left_byte, width_right_byte];
let width = u16::from_be_bytes(number);
println!("Left Byte: {width_left_byte}, Right Byte: {width_right_byte}, Byte Pair: {width}");
let gtable_prune = &contents[762..];
let gtable_prune = &contents[width as usize + 2 ..];
// Generate the glyph atlas
let mut glyph_atlas: Vec<Glyph> = vec![];
@ -59,22 +57,13 @@ pub fn generate_glyph_atlas() -> Vec<Glyph> {
if gtable_prune[position] == 1 {
new_glyph.push(Point::new(x as i32, y as i32));
}
/* // Debug info
print!("Glyph num: {glyph:2.} | Addr: {p:3.} | Line: {multiplier:5.} | Pos: {position:5.}");
if gtable_prune[position] == 1 {
println!(" | X: {x:2.} | Y: {y:2.}");
} else {
println!();
}
*/
}
glyph_atlas.push(new_glyph);
}
glyph_atlas
}
/// Method for generating points to render, using given string
pub fn draw_text(content: &str, glyph_atlas: Vec<Glyph>) -> Vec<Point> {
let mut points: Vec<Point> = vec![];
@ -102,3 +91,30 @@ pub fn draw_text(content: &str, glyph_atlas: Vec<Glyph>) -> Vec<Point> {
}
points
}
pub fn draw_cursor(content: &str, mut cursor_position: usize) -> (Point, Point) {
let mut x = 0;
let mut y = 0;
if cursor_position > 0 {
cursor_position = cursor_position.checked_sub(1).unwrap_or(0);
for (idx, chara) in content.chars().enumerate() {
x += 1;
if chara == '\n' {
x = 0;
y += 1;
}
if idx == cursor_position {
let point_a = Point::new((x * GLYPH_WIDTH) as i32,
(y * GLYPH_HEIGHT) as i32
);
let point_b = Point::new(point_a.x,
point_a.y + GLYPH_HEIGHT as i32
);
return (point_a, point_b)
}
}
}
(Point::new(0, 0), Point::new(0, GLYPH_HEIGHT as i32))
}

@ -1,8 +1,5 @@
extern crate sdl2;
use std::path::Path;
use font_build::draw_text;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
@ -38,14 +35,11 @@ fn get_corner_rect(rect_width: u32, rect_height: u32) -> Rect {
pub fn main() -> Result<(), String> {
let glyph_atlas = font_build::generate_glyph_atlas();
let font_path: &Path = Path::new("./fonts/Monoid-Regular.ttf");
let sdl_context = sdl2::init()?;
let video_subsys = sdl_context.video()?;
let ttf_context = sdl2::ttf::init().map_err(|e| e.to_string())?;
let window = video_subsys
.window("SDL2_TTF Example", SCREEN_WIDTH, SCREEN_HEIGHT)
.window("Rude", SCREEN_WIDTH, SCREEN_HEIGHT)
.position_centered()
.opengl()
.build()
@ -53,146 +47,148 @@ pub fn main() -> Result<(), String> {
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
// Load a font
let mut font = ttf_context.load_font(font_path, 12)?;
font.set_style(sdl2::ttf::FontStyle::BOLD);
let mut buffer = String::new();
let mut cursor_position = 0;
let mut draw_text = |text: &str| -> Result<(), String> {
let mut draw_text = |text: &str, pos: usize| -> Result<(), String> {
// Draw background
canvas.set_draw_color(Color::RGB(32, 32, 32));
canvas.clear();
// Draw text
canvas.set_draw_color(Color::RGB(240, 240, 240));
let fb_text = draw_text(text, glyph_atlas.clone());
let fb_text = font_build::draw_text(text, glyph_atlas.clone());
canvas.draw_points(&fb_text[..])?;
// Draw cursor
canvas.set_draw_color(Color::RGB(64, 240, 240));
let fb_cursor = font_build::draw_cursor(text, pos);
canvas.draw_line(fb_cursor.0, fb_cursor.1)?;
canvas.present();
Ok(())
};
draw_text(" ")?;
draw_text("", cursor_position)?;
let mut modifier_keys = ModifierKeys {alt: false, ctrl: false, shift: false};
'mainloop: loop {
// TODO: Make this completely user-configurable instead of hardcoded
for event in sdl_context.event_pump()?.poll_iter() {
match event {
// ESC or SIGKILL
Event::KeyDown { keycode: Some(Keycode::Escape), .. } |
Event::Quit { .. } => break 'mainloop,
// ALT down
Event::KeyDown { keycode: Some(Keycode::LAlt), .. } |
Event::KeyDown { keycode: Some(Keycode::RAlt), .. } => {
modifier_keys.alt = true
},
// ALT up
Event::KeyUp { keycode: Some(Keycode::LAlt), .. } |
Event::KeyUp { keycode: Some(Keycode::RAlt), .. } => {
modifier_keys.alt = false
},
// CTRL down
Event::KeyDown { keycode: Some(Keycode::LCtrl), .. } |
Event::KeyDown { keycode: Some(Keycode::RCtrl), .. } => {
modifier_keys.ctrl = true
},
// CTRL up
Event::KeyUp { keycode: Some(Keycode::LCtrl), .. } |
Event::KeyUp { keycode: Some(Keycode::RCtrl), .. } => {
modifier_keys.ctrl = false
},
// SHIFT down
Event::KeyDown { keycode: Some(Keycode::LShift), .. } |
Event::KeyDown { keycode: Some(Keycode::RShift), .. } => {
modifier_keys.shift = true
},
// SHIFT up
Event::KeyUp { keycode: Some(Keycode::LShift), .. } |
Event::KeyUp { keycode: Some(Keycode::RShift), .. } => {
modifier_keys.shift = false
},
// Ignore SUPER
Event::KeyDown { keycode: Some(Keycode::LGui), .. } |
Event::KeyDown { keycode: Some(Keycode::RGui), .. } => (),
Event::KeyUp { keycode, .. } => {
match keycode{
Some(Keycode::LAlt) | Some(Keycode::RAlt) => {
modifier_keys.alt = false
},
// Type spacebar
Event::KeyDown { keycode: Some(Keycode::Space), .. } => {
buffer.insert(cursor_position, ' ');
cursor_position += 1;
draw_text(&buffer)?
},
// Backspace
Event::KeyDown { keycode: Some(Keycode::Backspace), .. } => {
buffer.remove(cursor_position - 1);
cursor_position -= 1;
draw_text(&buffer)?
},
// Enter
Event::KeyDown { keycode: Some(Keycode::Return), .. } => {
let key = '\n';
buffer.insert(cursor_position, key);
cursor_position += 1;
draw_text(&buffer)?
},
Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => {
modifier_keys.ctrl = false
},
// Left/Back arrow
Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
cursor_position = usize::checked_sub(cursor_position, 1)
.unwrap_or(0)
},
Some(Keycode::LShift) | Some(Keycode::RShift) => {
modifier_keys.shift = false
},
// Home key
Event::KeyDown { keycode: Some(Keycode::Home), .. } => {
cursor_position = 0
},
Some(Keycode::LGui) | Some(Keycode::RGui) => {
break
},
// End key
Event::KeyDown { keycode: Some(Keycode::End), .. } => {
cursor_position = buffer.len()
_ => (),
}
},
// Right/Forward arrow
Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
cursor_position = (cursor_position + 1).min(buffer.len())
Event::KeyDown { keycode, .. } => {
match keycode {
Some(Keycode::LAlt) | Some(Keycode::RAlt) => {
modifier_keys.alt = true
},
Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => {
modifier_keys.ctrl = true
},
Some(Keycode::LShift) | Some(Keycode::RShift) => {
modifier_keys.shift = true
},
Some(Keycode::LGui) | Some(Keycode::RGui) => {
break
},
// BACKSPACE key
Some(Keycode::Backspace) => {
if buffer.len() > 0 {
buffer.remove(cursor_position - 1);
cursor_position -= 1;
draw_text(&buffer, cursor_position)?
}
},
// DELETE key
Some(Keycode::Delete) => {
if buffer.len() > 0 && cursor_position < buffer.len() {
buffer.remove(cursor_position);
draw_text(&buffer, cursor_position)?
}
},
// ENTER key
Some(Keycode::Return) => {
let key = '\n';
buffer.insert(cursor_position, key);
cursor_position += 1;
draw_text(&buffer, cursor_position)?
},
// HOME key
Some(Keycode::Home) => {
cursor_position = 0;
draw_text(&buffer, cursor_position)?
},
// END key
Some(Keycode::End) => {
cursor_position = buffer.len();
draw_text(&buffer, cursor_position)?
},
// Left/Back arrow
Some(Keycode::Left) => {
cursor_position = usize::checked_sub(cursor_position, 1)
.unwrap_or(0);
draw_text(&buffer, cursor_position)?
},
// Right/Forward arrow
Some(Keycode::Right) => {
cursor_position = (cursor_position + 1).min(buffer.len());
draw_text(&buffer, cursor_position)?
},
_ => (),
}
},
Event::TextInput { text, .. } => {
println!("{text}")
if !modifier_keys.alt && !modifier_keys.ctrl {
let input_char = text.chars().nth(0).expect("Empty");
buffer.insert(cursor_position, input_char);
cursor_position += 1;
draw_text(&buffer, cursor_position)?;
}
},
Event::KeyDown { keycode, .. } => {
let key = keycode.unwrap().to_string();
// Ignore multi-char keycodes
if key.len() != 1 { break }
let key_case = match modifier_keys.shift {
true => key.to_uppercase(),
false => key.to_lowercase()
}.chars().nth(0).expect("Empty");
buffer.insert(cursor_position, key_case);
cursor_position += 1;
draw_text(&buffer)?;
//println!("{key}");
},
_ => {}
}
}
}
println!("{buffer}");
Ok(())
}

Loading…
Cancel
Save