diff --git a/Cargo.lock b/Cargo.lock index 7e51b54..c0b47e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "c_vec" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd7a427adc0135366d99db65b36dae9237130997e560ed61118041fb72be6e8" + [[package]] name = "cfg-if" version = "1.0.0" @@ -40,6 +46,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7959277b623f1fb9e04aea73686c3ca52f01b2145f8ea16f4ff30d8b7623b1a" dependencies = [ "bitflags", + "c_vec", "lazy_static", "libc", "sdl2-sys", diff --git a/Cargo.toml b/Cargo.toml index 1474919..1841ad2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -sdl2 = "0.35.2" +sdl2 = { version = "0.35.2", features = ["gfx", "ttf"] } diff --git a/flake.nix b/flake.nix index e56eb54..efc746a 100644 --- a/flake.nix +++ b/flake.nix @@ -26,20 +26,21 @@ systems = nixpkgs.lib.systems.flakeExposed; perSystem = { config, self', inputs', pkgs, system, ... }: let - toolchain = pkgs.rust-bin.stable.latest.default; + toolchain = pkgs.rust-bin.stable.latest.complete; naersk-lib = pkgs.callPackage naersk { cargo = toolchain; rustc = toolchain; }; + deps = with pkgs; [ SDL2 SDL2_gfx SDL2_ttf ]; in { packages.default = naersk-lib.buildPackage { src = ./.; - buildInputs = with pkgs; [ SDL2 ]; + buildInputs = deps; }; apps.default.program = "${config.packages.default}/bin/medit"; devShells.default = pkgs.mkShell { - nativeBuildInputs = [ toolchain ]; + nativeBuildInputs = [ toolchain ] ++ deps; }; }; }; diff --git a/resources/fonts/ttf/FiraCode-Bold.ttf b/resources/fonts/ttf/FiraCode-Bold.ttf new file mode 100644 index 0000000..f891bde Binary files /dev/null and b/resources/fonts/ttf/FiraCode-Bold.ttf differ diff --git a/resources/fonts/ttf/FiraCode-Light.ttf b/resources/fonts/ttf/FiraCode-Light.ttf new file mode 100644 index 0000000..5664ec3 Binary files /dev/null and b/resources/fonts/ttf/FiraCode-Light.ttf differ diff --git a/resources/fonts/ttf/FiraCode-Medium.ttf b/resources/fonts/ttf/FiraCode-Medium.ttf new file mode 100644 index 0000000..2c0ecdf Binary files /dev/null and b/resources/fonts/ttf/FiraCode-Medium.ttf differ diff --git a/resources/fonts/ttf/FiraCode-Regular.ttf b/resources/fonts/ttf/FiraCode-Regular.ttf new file mode 100644 index 0000000..bd73685 Binary files /dev/null and b/resources/fonts/ttf/FiraCode-Regular.ttf differ diff --git a/resources/fonts/ttf/FiraCode-Retina.ttf b/resources/fonts/ttf/FiraCode-Retina.ttf new file mode 100644 index 0000000..660742d Binary files /dev/null and b/resources/fonts/ttf/FiraCode-Retina.ttf differ diff --git a/resources/fonts/ttf/FiraCode-SemiBold.ttf b/resources/fonts/ttf/FiraCode-SemiBold.ttf new file mode 100644 index 0000000..d8dcef6 Binary files /dev/null and b/resources/fonts/ttf/FiraCode-SemiBold.ttf differ diff --git a/resources/fonts/ttf/FiraCode-VF.ttf b/resources/fonts/ttf/FiraCode-VF.ttf new file mode 100644 index 0000000..c05ac82 Binary files /dev/null and b/resources/fonts/ttf/FiraCode-VF.ttf differ diff --git a/src/main.rs b/src/main.rs index 2f8c740..90a51b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,23 +1,44 @@ -use sdl2::{event::Event, init, keyboard::Keycode, pixels::Color}; +use sdl2::event::Event; +use sdl2::keyboard::Keycode; +use sdl2::pixels::Color; +use sdl2::rect::Rect; +use sdl2::render::Texture; +use sdl2::render::TextureCreator; +use sdl2::render::TextureQuery; +use sdl2::ttf; +use sdl2::ttf::Font; +use sdl2::video::WindowContext; -fn main() { - let ctx = init().unwrap(); - let vid = ctx.video().unwrap(); - let win = vid - .window("medit", 800, 600) +fn string_err(e: impl ToString) -> String { + e.to_string() +} + +const WIDTH: u32 = 800; +const HEIGHT: u32 = 600; + +fn main() -> Result<(), String> { + let context = sdl2::init()?; + let video = context.video()?; + let ttf_context = ttf::init().map_err(string_err)?; + + let window = video + .window("medit", WIDTH, HEIGHT) .position_centered() + .allow_highdpi() .build() - .unwrap(); - let mut can = win.into_canvas().build().unwrap(); - can.set_draw_color(Color::RGB(0, 255, 255)); - can.clear(); - can.present(); - let mut event_pump = ctx.event_pump().unwrap(); - let mut i = 0; + .map_err(string_err)?; + + let mut canvas = window.into_canvas().build().map_err(string_err)?; + let texture_creator = canvas.texture_creator(); + + let font = ttf_context.load_font("resources/fonts/ttf/FiraCode-VF.ttf", 128)?; + + canvas.set_draw_color(Color::WHITE); + canvas.clear(); + + let mut event_pump = context.event_pump()?; + let mut x = 0; 'running: loop { - i = (i + 1) % 255; - can.set_draw_color(Color::RGB(i, 64, 255 - i)); - can.clear(); for event in event_pump.poll_iter() { match event { Event::Quit { .. } @@ -25,12 +46,46 @@ fn main() { keycode: Some(Keycode::Escape), .. } => break 'running, + Event::KeyDown { + keycode: Some(k), .. + } if is_drawable_key(k) => { + canvas.clear(); + let texture = string_texture(&font, &texture_creator, k.name())?; + let target = target_rect(x, 0, &texture); + x += target.width() as i32; + canvas.copy(&texture, None, Some(target))?; + } _ => {} } } - // The rest of the game loop goes here... - - can.present(); + canvas.present(); std::thread::sleep(std::time::Duration::new(0, 1_000_000_000u32 / 60)); } + Ok(()) +} + +fn is_drawable_key(key: Keycode) -> bool { + let key = key as i32; + (key >= Keycode::A as i32 && key <= Keycode::Z as i32) + || (key >= Keycode::Num0 as i32 && key <= Keycode::Num9 as i32) +} + +fn string_texture<'f, 't>( + font: &Font<'f, 'f>, + texture_creator: &'t TextureCreator, + string: impl AsRef, +) -> Result, String> { + let surface = font + .render(string.as_ref()) + .blended(Color::BLACK) + .map_err(string_err)?; + texture_creator + .create_texture_from_surface(surface) + .map_err(string_err) +} + +fn target_rect(x: i32, y: i32, texture: &Texture) -> Rect { + let TextureQuery { width, height, .. } = texture.query(); + + Rect::new(x, y, width, height) }