From 289c318804a11f1406e5400cc455360eb5e9f4a0 Mon Sep 17 00:00:00 2001 From: korin Date: Wed, 5 Apr 2023 22:48:45 -0400 Subject: [PATCH] main --- src/_catlas.rs | 31 ++++++ src/font_build.rs | 14 +++ src/main.rs | 234 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 src/_catlas.rs create mode 100644 src/font_build.rs create mode 100644 src/main.rs diff --git a/src/_catlas.rs b/src/_catlas.rs new file mode 100644 index 0000000..aa57135 --- /dev/null +++ b/src/_catlas.rs @@ -0,0 +1,31 @@ +//let sdl_context = sdl2::init()?; +//let video_subsys = sdl_context.video()?; +//let ttf_context = sdl2::ttf::init().map_err(|e| e.to_string())?; + +const GLYPH_METRICS_CAPACITY: usize = 128; + +struct GlyphMetric { + ax: f32, // advance.x + ay: f32, // advance.y + + bw: f32, // bitmap.width; + bh: f32, // bitmap.rows; + + bl: f32, // bitmap_left; + bt: f32, // bitmap_top; + + tx: f32, // x offset of glyph in texture coordinates +} + +struct FreeGlyphAtlas { + atlas_width: usize, // TODO: Get FT_Uint from FT2build + atlas_height: usize, + glyphs_texture: GLuint, + metrics: [GlyphMetric; GLYPH_METRICS_CAPACITY], +} + +fn free_glyph_atlas_init(atlas: FreeGlyphAtlas, face: FT_Face) { + for i in 32..127 { + // something something sdl2::ttf::GlyphMetrics + } +} diff --git a/src/font_build.rs b/src/font_build.rs new file mode 100644 index 0000000..0abfdef --- /dev/null +++ b/src/font_build.rs @@ -0,0 +1,14 @@ +use std::fs; + +struct TypeFace { + type_char: [[bool; 8]; 14], +} + +fn get_font() { + let file_path = "./fonts/Terminus14x8.data"; + + println!("In file {}", file_path); + + let contents = fs::read_to_string(file_path) + .expect("File could not be read"); +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..15e50c7 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,234 @@ +extern crate sdl2; + +use std::path::Path; + +use sdl2::event::Event; +use sdl2::keyboard::Keycode; +use sdl2::pixels::Color; +use sdl2::rect::Rect; +use sdl2::render::TextureQuery; + +//mod _catlas; +//use _catlas::*; + +mod font_build; +use font_build::*; + +static SCREEN_WIDTH: u32 = 1680; +static SCREEN_HEIGHT: u32 = 945; + +struct ModifierKeys { + alt: bool, + ctrl: bool, + shift: bool, +} + +// handle the annoying Rect i32 +macro_rules! rect( + ($x:expr, $y:expr, $w:expr, $h:expr) => ( + Rect::new($x as i32, $y as i32, $w as u32, $h as u32) + ) +); + +// Scale fonts to a reasonable size when they're too big (though they might look less smooth) +/* +fn get_centered_rect(rect_width: u32, rect_height: u32, cons_width: u32, cons_height: u32) -> Rect { + let wr = rect_width as f32 / cons_width as f32; + let hr = rect_height as f32 / cons_height as f32; + + let (w, h) = if wr > 1f32 || hr > 1f32 { + if wr > hr { + println!("Scaling down! The text will look worse!"); + let h = (rect_height as f32 / wr) as i32; + (cons_width as i32, h) + } else { + println!("Scaling down! The text will look worse!"); + let w = (rect_width as f32 / hr) as i32; + (w, cons_height as i32) + } + } else { + (rect_width as i32, rect_height as i32) + }; + + let cx = (SCREEN_WIDTH as i32 - w) / 2; + let cy = (SCREEN_HEIGHT as i32 - h) / 2; + rect!(cx, cy, w, h) +} +*/ + +fn get_corner_rect(rect_width: u32, rect_height: u32) -> Rect { + let (w,h) = (rect_width as i32, rect_height as i32); + let cx = 15; + let cy = 15; + rect!(cx, cy, w, h) +} + + +pub fn main() -> Result<(), String> { + 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) + .position_centered() + .opengl() + .build() + .map_err(|e| e.to_string())?; + + let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?; + let texture_creator = canvas.texture_creator(); + + // 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> { + // render a surface, and convert it to a texture bound to the canvas + let surface = font + .render(text) + .blended(Color::RGBA(255, 255, 255, 255)) + .map_err(|e| e.to_string())?; + let texture = texture_creator + .create_texture_from_surface(&surface) + .map_err(|e| e.to_string())?; + + canvas.set_draw_color(Color::RGB(32, 32, 32)); + canvas.clear(); + + let TextureQuery { width, height, .. } = texture.query(); + + // If the example text is too big for the screen, downscale it (and center regardless) + // let padding = 64; + let target = get_corner_rect( + width, + height, + ); + + canvas.copy(&texture, None, Some(target))?; + canvas.present(); + + Ok(()) + }; + + let mut modifier_keys = ModifierKeys {alt: false, ctrl: false, shift: false}; + + 'mainloop: loop { + 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), .. } => (), + + // 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)? + }, + + // Left/Back arrow + Event::KeyDown { keycode: Some(Keycode::Left), .. } => { + cursor_position = usize::checked_sub(cursor_position, 1) + .unwrap_or(0) + }, + + // Home key + Event::KeyDown { keycode: Some(Keycode::Home), .. } => { + cursor_position = 0 + }, + + // 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, .. } => { + 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}"); + }, + + _ => {} + } + } + } + + Ok(()) +}