From 963c729bcdc1e5f82890f96bc55f1532f6eaf763 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sun, 5 Jun 2022 16:17:11 +0200 Subject: thing --- src/lib.rs | 9 +++ src/main.rs | 182 +++++++++++++++++++------------------------------------ src/pattern.rs | 40 ++++++++++++ src/transform.rs | 24 ++++++++ 4 files changed, 136 insertions(+), 119 deletions(-) create mode 100644 src/lib.rs create mode 100644 src/pattern.rs create mode 100644 src/transform.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..76b35c9 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,9 @@ +use color::Color; + +pub mod color; +pub mod transform; +pub mod pattern; + +pub trait Sample { + fn sample(&mut self, x: f64, y: f64) -> Color; +} diff --git a/src/main.rs b/src/main.rs index d8c4a21..a0f7e9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,12 @@ #![feature(box_syntax)] -pub mod color; use anyhow::Result; -use color::Color; +use blubcat::{ + color::Color, + pattern::{Rainbow, Sequence, Solid, Gradient}, + transform::{Matrix, Polar}, + Sample, +}; use std::{ env, f64::consts::PI, @@ -12,17 +16,17 @@ use std::{ }; static HELP: &str = " -Usage: blubcat [PATTERN] [FILE]... +Usage: blubcat [PATTERN] [FILE...] Concatenate FILE(s) to standard output, colorizing the output according to PATTERN. With no FILE, or when FILE is -, the standard input is read. If PATTERN is repeated only the last one will be used. PATTERN: - -R --rainbow Rainbow + -R --rainbow Sinebow -S --sequence Sequences colors on the X-axis -G --gradient Interpolates the colors on the X-axis - + Push mulple patterns to a stack, then process them with transform TRANSFORM: @@ -31,7 +35,9 @@ TRANSFORM: -m --matrix PRESET: - -P --pride Pride flag + --zebra + --pride --trans + --ukraine ofc the this needed :) COLOR: @@ -42,7 +48,7 @@ COLOR: fn main() -> Result<()> { let mut args = env::args().skip(1); - let mut pat: Box = box Solid(Color::WHITE); + let mut pat: Vec> = vec![]; loop { let a = args.next(); @@ -58,6 +64,7 @@ fn main() -> Result<()> { if !a.starts_with("-") || a == "--" || a == "-" { break; } + let mut push_queue: Vec> = vec![]; match a.as_str() { "-?" | "--help" => { println!("{}", HELP); @@ -65,70 +72,62 @@ fn main() -> Result<()> { } /* PRESETS */ - "-P" | "--pride" => { - pat = box Transform { - matrix: ((1.0 / 12.0, 1.0 / 12.0), (0.0, 0.0)), - inner: box Extend(box Sequence(vec![ - Color::parse("e50000").unwrap(), - Color::parse("ff8d00").unwrap(), - Color::parse("ffee00").unwrap(), - Color::parse("028121").unwrap(), - Color::parse("004cff").unwrap(), - Color::parse("770088").unwrap(), - ])), - } - } + "--pride" => pat.push(flag_helper(&[ + "e50000", "ff8d00", "ffee00", "028121", "004cff", "770088", + ])), + "--zebra" => pat.push(flag_helper(&["000000", "ffffff"])), + "--trans" => pat.push(flag_helper(&[ + "5bcffb", "f5abb9", "ffffff", "f5abb9", "5bcffb", + ])), + "--ukraine" => pat.push(flag_helper(&["0057B8", "FFD700"])), /* PATTERNS */ - "-R" | "--rainbow" => pat = box Extend(box Rainbow), - "-S" | "--sequence" => { - pat = box Extend(box Sequence( - arg_next() - .unwrap() - .split(",") - .map(|e| Color::parse(e).expect("color invalid")) - .collect::>(), - )) - } - "-G" | "--gradient" => { - pat = box Extend(box Gradient( - arg_next() - .unwrap() - .split(",") - .map(|e| Color::parse(e).expect("color invalid")) - .collect::>(), - )) - } + "-R" | "--rainbow" => pat.push(box Rainbow), + "-S" | "--sequence" => pat.push(box Sequence( + arg_next() + .unwrap() + .split(",") + .map(|e| Color::parse(e).expect("color invalid")) + .collect::>(), + )), + "-G" | "--gradient" => pat.push(box Gradient( + arg_next() + .unwrap() + .split(",") + .map(|e| Color::parse(e).expect("color invalid")) + .collect::>(), + )), /* TRANSFORMS */ "-s" | "--scale" => { let fac = arg_num(); - pat = box Transform { - inner: pat, + push_queue.push(box Matrix { + inner: pat.pop().unwrap(), matrix: ((fac, 0.0), (0.0, fac)), - } + }) } "-r" | "--rotate" => { let angle = arg_num() * PI * 2.0; - pat = box Transform { - inner: pat, + push_queue.push(box Matrix { + inner: pat.pop().unwrap(), matrix: ((angle.cos(), -angle.sin()), (angle.sin(), angle.cos())), - } - } - "-m" | "--matrix" => { - pat = box Transform { - inner: pat, - matrix: ((arg_num(), arg_num()), (arg_num(), arg_num())), - } + }) } + "-m" | "--matrix" => push_queue.push(box Matrix { + inner: pat.pop().unwrap(), + matrix: ((arg_num(), arg_num()), (arg_num(), arg_num())), + }), + "-p" | "--polar" => push_queue.push(box Polar(pat.pop().unwrap())), _ => panic!("unknown option {}", &a), } + pat.extend(push_queue.drain(..)) } else { break; } } let inputs = args.collect::>(); + let mut pat = pat.pop().unwrap_or_else(|| box Solid(Color::WHITE)); if inputs.len() == 0 { colorize(stdin(), &mut pat)? @@ -141,7 +140,19 @@ fn main() -> Result<()> { Ok(()) } -fn colorize(file: impl Read, sampler: &mut Box) -> Result<()> { +fn flag_helper(colors: &[&str]) -> Box { + box Matrix { + matrix: ((1.0 / 12.0, 1.0 / 12.0), (0.0, 0.0)), + inner: box Sequence( + colors + .into_iter() + .map(|e| Color::parse(e).unwrap()) + .collect(), + ), + } +} + +fn colorize(file: impl Read, sampler: &mut Box) -> Result<()> { let mut file = BufReader::new(file); let mut line = String::new(); for y in 0.. { @@ -156,70 +167,3 @@ fn colorize(file: impl Read, sampler: &mut Box) -> Result<()> { } Ok(()) } - -trait Sample2D { - fn sample(&mut self, x: f64, y: f64) -> Color; -} -trait Sample1D { - fn sample(&mut self, x: f64) -> Color; -} - -struct Extend(Box); -impl Sample2D for Extend { - fn sample(&mut self, x: f64, _y: f64) -> Color { - self.0.sample(x) - } -} - -struct Transform { - pub inner: Box, - pub matrix: ((f64, f64), (f64, f64)), -} -impl Sample2D for Transform { - fn sample(&mut self, x: f64, y: f64) -> Color { - let (x, y) = ( - x * self.matrix.0 .0 + y * self.matrix.0 .1, - x * self.matrix.1 .0 + y * self.matrix.1 .1, - ); - self.inner.sample(x, y) - } -} - -struct Rainbow; -impl Sample1D for Rainbow { - fn sample(&mut self, x: f64) -> Color { - static PI: f64 = 3.14; - let x = x * PI * 2.0; - return Color { - r: (x + PI / 3.0 * 0.0).sin() * 0.5 + 0.5, - g: (x + PI / 3.0 * 2.0).sin() * 0.5 + 0.5, - b: (x + PI / 3.0 * 4.0).sin() * 0.5 + 0.5, - }; - } -} - -struct Sequence(pub Vec); -impl Sample1D for Sequence { - fn sample(&mut self, x: f64) -> Color { - self.0[(x * self.0.len() as f64).floor() as usize % self.0.len()] - } -} - -struct Gradient(pub Vec); -impl Sample1D for Gradient { - fn sample(&mut self, x: f64) -> Color { - let index = x * self.0.len() as f64; - let index_int = index.floor() as usize; - let index_error = index % 1.0; - let a = self.0[index_int % self.0.len()]; - let b = self.0[(index_int + 1) % self.0.len()]; - Color::mix(a, b, index_error) - } -} - -struct Solid(Color); -impl Sample2D for Solid { - fn sample(&mut self, _x: f64, _y: f64) -> Color { - self.0 - } -} diff --git a/src/pattern.rs b/src/pattern.rs new file mode 100644 index 0000000..ba9899e --- /dev/null +++ b/src/pattern.rs @@ -0,0 +1,40 @@ +use crate::{color::Color, Sample}; + +pub struct Rainbow; +impl Sample for Rainbow { + fn sample(&mut self, x: f64, _y: f64) -> Color { + static PI: f64 = 3.14; + let x = x * PI * 2.0; + return Color { + r: (x + PI / 3.0 * 0.0).sin() * 0.5 + 0.5, + g: (x + PI / 3.0 * 2.0).sin() * 0.5 + 0.5, + b: (x + PI / 3.0 * 4.0).sin() * 0.5 + 0.5, + }; + } +} + +pub struct Sequence(pub Vec); +impl Sample for Sequence { + fn sample(&mut self, x: f64, _y: f64) -> Color { + self.0[(x * self.0.len() as f64).floor() as usize % self.0.len()] + } +} + +pub struct Gradient(pub Vec); +impl Sample for Gradient { + fn sample(&mut self, x: f64, _y: f64) -> Color { + let index = x * self.0.len() as f64; + let index_int = index.floor() as usize; + let index_error = index % 1.0; + let a = self.0[index_int % self.0.len()]; + let b = self.0[(index_int + 1) % self.0.len()]; + Color::mix(a, b, index_error) + } +} + +pub struct Solid(pub Color); +impl Sample for Solid { + fn sample(&mut self, _x: f64, _y: f64) -> Color { + self.0 + } +} diff --git a/src/transform.rs b/src/transform.rs new file mode 100644 index 0000000..8b555d1 --- /dev/null +++ b/src/transform.rs @@ -0,0 +1,24 @@ +use crate::{color::Color, Sample}; + +pub struct Matrix { + pub inner: Box, + pub matrix: ((f64, f64), (f64, f64)), +} +impl Sample for Matrix { + fn sample(&mut self, x: f64, y: f64) -> Color { + let (x, y) = ( + x * self.matrix.0 .0 + y * self.matrix.0 .1, + x * self.matrix.1 .0 + y * self.matrix.1 .1, + ); + self.inner.sample(x, y) + } +} + +pub struct Polar(pub Box); +impl Sample for Polar { + fn sample(&mut self, x: f64, y: f64) -> Color { + let ang = x.atan2(y); + let dist = (x * x + y * y).sqrt(); + self.0.sample(ang, dist) + } +} -- cgit v1.2.3-70-g09d2