Compare commits
5 Commits
7a47787747
...
749eb31616
| Author | SHA1 | Date |
|---|---|---|
|
|
749eb31616 | 3 years ago |
|
|
bebacf1dfe | 3 years ago |
|
|
4791b3cfb9 | 3 years ago |
|
|
75f315c646 | 3 years ago |
|
|
9d38959258 | 3 years ago |
12 changed files with 335 additions and 241 deletions
@ -0,0 +1 @@ |
|||||||
|
/target |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
[package] |
||||||
|
name = "rude" |
||||||
|
version = "0.1.0" |
||||||
|
edition = "2021" |
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||||
|
[profile.release] |
||||||
|
opt-level = 3 |
||||||
|
|
||||||
|
[dependencies] |
||||||
|
sdl2 = { version = "0.35.2" } |
||||||
@ -0,0 +1,49 @@ |
|||||||
|
#+title: Todo List |
||||||
|
|
||||||
|
* Movement [0/3] |
||||||
|
- [-] Arrow keys [1/4] |
||||||
|
* [X] L/R (char/char) |
||||||
|
* [ ] L/R (word/word) |
||||||
|
* [ ] L/R (sentence/sentence) |
||||||
|
* [ ] Up and down (line by line) |
||||||
|
- [-] HOME and END keys [1/2] |
||||||
|
* [X] Start to end of document |
||||||
|
* [ ] Confine to line unless CTRL is pressed |
||||||
|
- [ ] Mouse input |
||||||
|
|
||||||
|
* Editing [0/5] |
||||||
|
- [ ] Type text |
||||||
|
- [-] Remove text [3/6] |
||||||
|
* [X] Character backspace |
||||||
|
* [X] Character delete |
||||||
|
* [X] Word backspace |
||||||
|
* [ ] Word delete |
||||||
|
* [ ] Sentence backspace |
||||||
|
* [ ] Sentence delete |
||||||
|
- [ ] Select text |
||||||
|
- [ ] Cut, Copy, & Paste |
||||||
|
- [ ] Undo / Redo |
||||||
|
|
||||||
|
* Rendering [1/6] |
||||||
|
- [-] Text [1/3] |
||||||
|
* [X] Redneck bitmap |
||||||
|
* [ ] Refined bitmap (.otb format) |
||||||
|
* [ ] Vector (.ttf, .otf, etc) |
||||||
|
- [X] Cursor |
||||||
|
- [ ] Selection |
||||||
|
- [ ] Scaling/Zoom |
||||||
|
- [ ] Scrolling |
||||||
|
- [ ] Syntax Highlighting [/] |
||||||
|
- [ ] Built-in basic Rust highlighting |
||||||
|
|
||||||
|
* Misc [0/3] |
||||||
|
- [ ] Search [0/1] |
||||||
|
- [ ] Regex support |
||||||
|
- [ ] Replace [0/2] |
||||||
|
- [ ] Regex support |
||||||
|
- [ ] Sed style |
||||||
|
- [ ] File handling [0/3] |
||||||
|
- [ ] Open files |
||||||
|
- [ ] Save files |
||||||
|
- [ ] Save files as |
||||||
|
- [ ] Folder handling (for projects) |
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,120 @@ |
|||||||
|
//! A redneck bitmap font renderer
|
||||||
|
//!
|
||||||
|
//! This takes a janky ass raw image file with width info inserted
|
||||||
|
//! and turns it into a bunch of points for SDL2 to read.
|
||||||
|
|
||||||
|
use std::{fs::File, path::Path, io::Read}; |
||||||
|
|
||||||
|
use sdl2::rect::Point; |
||||||
|
|
||||||
|
const GLYPH_WIDTH: usize = 8; |
||||||
|
const GLYPH_HEIGHT: usize = 14; |
||||||
|
const GLYPH_AREA: usize = GLYPH_WIDTH * GLYPH_HEIGHT; |
||||||
|
type Glyph = Vec<Point>; |
||||||
|
|
||||||
|
/// Reads the file and turns it into a Vec of u8s
|
||||||
|
fn read_file(file_name: String) -> Vec<u8> { |
||||||
|
let path = Path::new(&file_name); |
||||||
|
|
||||||
|
if !path.exists() { |
||||||
|
return String::from("Not Found!").into(); |
||||||
|
} |
||||||
|
|
||||||
|
let mut file_content = Vec::new(); |
||||||
|
let mut file = File::open(&file_name).expect("Unable to open file"); |
||||||
|
file.read_to_end(&mut file_content).expect("Unable to read"); |
||||||
|
|
||||||
|
file_content |
||||||
|
} |
||||||
|
|
||||||
|
pub fn generate_glyph_atlas() -> Vec<Glyph> { |
||||||
|
// Retrieve font data from file
|
||||||
|
let file_path = String::from("./fonts/Terminus14x8.data"); |
||||||
|
let contents = read_file(file_path); |
||||||
|
|
||||||
|
// Get width of image for proper positioning of pixels
|
||||||
|
let width_left_byte = contents[0]; |
||||||
|
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[width as usize + 2 ..]; |
||||||
|
|
||||||
|
// Generate the glyph atlas
|
||||||
|
let mut glyph_atlas: Vec<Glyph> = vec![]; |
||||||
|
for glyph in 0..96 { |
||||||
|
let mut new_glyph: Glyph = vec![]; |
||||||
|
|
||||||
|
for p in 0..GLYPH_AREA as u16 { |
||||||
|
let x = p % GLYPH_WIDTH as u16; |
||||||
|
let y = p / GLYPH_WIDTH as u16; |
||||||
|
|
||||||
|
let multiplier = y * width; |
||||||
|
let offset = glyph * GLYPH_WIDTH as u16; |
||||||
|
let position = (x as u16 + multiplier + offset) as usize; |
||||||
|
|
||||||
|
if gtable_prune[position] == 1 { |
||||||
|
new_glyph.push(Point::new(x as i32, y as i32)); |
||||||
|
} |
||||||
|
} |
||||||
|
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![]; |
||||||
|
|
||||||
|
let lines = content.split('\n'); |
||||||
|
for (y, chars) in lines.enumerate() { |
||||||
|
for (x, chara) in chars.chars().enumerate() { |
||||||
|
let index; |
||||||
|
if chara.is_lowercase() { |
||||||
|
index = chara.to_ascii_lowercase() as usize; |
||||||
|
} else { |
||||||
|
index = chara.to_ascii_uppercase() as usize; |
||||||
|
} |
||||||
|
|
||||||
|
for pixel in &glyph_atlas[index - 32] { |
||||||
|
let x_offset = x * GLYPH_WIDTH; |
||||||
|
let y_offset = y * GLYPH_HEIGHT; |
||||||
|
|
||||||
|
let positioned_pixel = Point::new( |
||||||
|
pixel.x + x_offset as i32, |
||||||
|
pixel.y + y_offset as i32, |
||||||
|
); |
||||||
|
points.push(positioned_pixel); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
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,69 +0,0 @@ |
|||||||
use std::{fs::File, path::Path, io::Read}; |
|
||||||
|
|
||||||
const GLYPH_WIDTH: usize = 8; |
|
||||||
const GLYPH_HEIGHT: usize = 14; |
|
||||||
const GLYPH_AREA: usize = GLYPH_WIDTH * GLYPH_HEIGHT; |
|
||||||
#[allow(dead_code)] |
|
||||||
type Glyph = [[bool; GLYPH_WIDTH]; GLYPH_HEIGHT]; |
|
||||||
|
|
||||||
/// Reads the file and turns it into a Vec of u8s
|
|
||||||
fn read_file(file_name: String) -> Vec<u8> { |
|
||||||
let path = Path::new(&file_name); |
|
||||||
|
|
||||||
if !path.exists() { |
|
||||||
return String::from("Not Found!").into(); |
|
||||||
} |
|
||||||
|
|
||||||
let mut file_content = Vec::new(); |
|
||||||
let mut file = File::open(&file_name).expect("Unable to open file"); |
|
||||||
file.read_to_end(&mut file_content).expect("Unable to read"); |
|
||||||
|
|
||||||
file_content |
|
||||||
} |
|
||||||
|
|
||||||
pub fn get_font() { |
|
||||||
// Retrieve font data from file
|
|
||||||
let file_path = String::from("./fonts/Terminus14x8.data"); |
|
||||||
println!("In file {file_path}"); |
|
||||||
|
|
||||||
let contents = read_file(file_path); |
|
||||||
|
|
||||||
let width_left_byte = contents[0]; |
|
||||||
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[2..].iter() |
|
||||||
.filter(|x| **x % 3 == 0) |
|
||||||
.collect::<Vec<_>>(); |
|
||||||
*/ |
|
||||||
// Remove useless Green and Blue data
|
|
||||||
let gtable_prune: Vec<u8> = contents[2..].iter() |
|
||||||
.enumerate() |
|
||||||
.filter(|x| x.0 % 3 == 0) |
|
||||||
.map(|(_, x)| *x) |
|
||||||
.collect(); |
|
||||||
|
|
||||||
println!("Pruned Glyph Table is {} long; it should be {}.", |
|
||||||
gtable_prune.len(), |
|
||||||
(contents.len() - 2) / 3 |
|
||||||
); |
|
||||||
|
|
||||||
let glyph_atlas: Vec<Glyph>; |
|
||||||
for glyph in 0..95 { |
|
||||||
let new_glyph: Glyph = [[false; GLYPH_WIDTH]; GLYPH_HEIGHT]; |
|
||||||
for p in 0..GLYPH_AREA as u16 { |
|
||||||
let multiplier = p / GLYPH_WIDTH as u16 * width; |
|
||||||
let offset = glyph * GLYPH_WIDTH as u16; |
|
||||||
let position = (p % GLYPH_WIDTH as u16 + multiplier + offset) as usize; |
|
||||||
|
|
||||||
println!("Glyph num: {glyph:2.} | Addr: {p:3.} | Line: {multiplier:5.} | Pos: {position:5.}"); |
|
||||||
|
|
||||||
if gtable_prune[position] == 255 { |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue