diff --git a/.gitignore b/.gitignore index 8a48101..b6b9fae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ /target .direnv -output.svg -layout.json \ No newline at end of file +output.svg \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index ff239f4..3d7b096 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,15 +67,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "csscolorparser" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" -dependencies = [ - "phf", -] - [[package]] name = "derive_more" version = "0.99.17" @@ -95,10 +86,8 @@ version = "0.1.0" dependencies = [ "askama", "derive_more", - "kle-serial", "lazy_static", "regex", - "serde_json", "strum", "strum_macros", ] @@ -118,23 +107,6 @@ dependencies = [ "libm", ] -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "kle-serial" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbb2235a7a2c256a7d0e6393a2f29b27995dc098b797c0fd02f418166709eae" -dependencies = [ - "csscolorparser", - "rgb", - "serde", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -200,48 +172,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.28", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - [[package]] name = "proc-macro2" version = "1.0.66" @@ -260,21 +190,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - [[package]] name = "regex" version = "1.9.3" @@ -304,12 +219,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" -[[package]] -name = "rgb" -version = "0.8.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" - [[package]] name = "rustc_version" version = "0.4.0" @@ -325,12 +234,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - [[package]] name = "semver" version = "1.0.18" @@ -357,23 +260,6 @@ dependencies = [ "syn 2.0.28", ] -[[package]] -name = "serde_json" -version = "1.0.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "siphasher" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" - [[package]] name = "strum" version = "0.25.0" diff --git a/dyesub-tool/Cargo.toml b/dyesub-tool/Cargo.toml index 4bf83bb..a99af79 100644 --- a/dyesub-tool/Cargo.toml +++ b/dyesub-tool/Cargo.toml @@ -6,9 +6,7 @@ edition = "2021" [dependencies] askama = "0.12.0" derive_more = "0.99.17" -kle-serial = "0.2.2" lazy_static = "1.4.0" regex = "1.9.3" -serde_json = "1.0.105" strum = "0.25.0" strum_macros = "0.25.2" diff --git a/dyesub-tool/src/key/mod.rs b/dyesub-tool/src/key/mod.rs new file mode 100644 index 0000000..28e3553 --- /dev/null +++ b/dyesub-tool/src/key/mod.rs @@ -0,0 +1,70 @@ +mod oyayubi; +pub use oyayubi::OYAYUBI; + +use std::fmt::{Display, self}; + +#[derive(Clone, Copy)] +pub enum Key<'a> { + Oyayubi { + latin: char, + normal: char, + shift: char, + alt_shift: Option, + }, + Single { + text: &'a str, + u: f64, + }, + Icon { + icon_path: &'a str, + u: f64, + }, + Break, +} + +pub const fn oyayubi<'a>(latin: char, normal: char, shift: char, alt_shift: Option) -> Key<'a> { + Key::Oyayubi { + latin, + normal, + shift, + alt_shift, + } +} + +pub const fn single<'a>(text: &'a str, u: f64) -> Key<'a> { + Key::Single { + text, + u, + } +} + +pub const fn icon<'a>(icon_path: &'a str, u: f64) -> Key<'a> { + Key::Icon { + icon_path, + u, + } +} + +impl<'a> Key<'a> { + pub fn width_mod(&self) -> f64 { + use Key::*; + match self { + Oyayubi { .. } => 1.0, + Single { u, .. } => *u, + Icon { u, .. } => *u, + Break => 0.0, + } + } +} + +impl<'a> Display for Key<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Key::*; + write!(f, "{}", match self { + Oyayubi { latin, .. } => latin.to_string(), + Single { text, .. } => text.to_string(), + Icon { icon_path, .. } => icon_path.to_string(), + Break => "".to_string(), + }) + } +} \ No newline at end of file diff --git a/dyesub-tool/src/key/oyayubi.rs b/dyesub-tool/src/key/oyayubi.rs new file mode 100644 index 0000000..ffffea5 --- /dev/null +++ b/dyesub-tool/src/key/oyayubi.rs @@ -0,0 +1,35 @@ +use super::Key; +use super::oyayubi as k; + +pub const OYAYUBI: [Key; 30] = [ + k('Q', '。', 'ぁ', None), + k('W', 'か', 'え', None), + k('E', 'た', 'り', None), + k('R', 'こ', 'ゃ', None), + k('T', 'さ', 'れ', None), + k('Y', 'ら', 'よ', Some('ぱ')), + k('U', 'ち', 'に', None), + k('I', 'く', 'る', None), + k('O', 'つ', 'ま', None), + k('P', ',', 'ぇ', Some('ぴ')), + k('A', 'う', 'を', None), + k('S', 'し', 'あ', None), + k('D', 'て', 'な', None), + k('F', 'け', 'ゅ', None), + k('G', 'せ', 'も', None), + k('H', 'は', 'み', None), + k('J', 'と', 'お', None), + k('K', 'き', 'の', None), + k('L', 'い', 'ょ', Some('ぽ')), + k(';', 'ん', 'っ', None), // Missing + + k('Z', '.', 'ぅ', None), + k('X', 'ひ', 'ー', None), + k('C', 'す', 'ろ', None), + k('V', 'ふ', 'や', None), + k('B', 'へ', 'ぃ', None), + k('N', 'め', 'ぬ', Some('ぷ')), + k('M', 'そ', 'ゆ', None), + k(',', 'ね', 'む', Some('ぺ')), // Missing < + k('.', 'ほ', 'わ', None), // Missing > + k('?', '・', 'ぉ', Some('ゎ')) // Missing / +]; \ No newline at end of file diff --git a/dyesub-tool/src/main.rs b/dyesub-tool/src/main.rs index e570512..0c0d63f 100644 --- a/dyesub-tool/src/main.rs +++ b/dyesub-tool/src/main.rs @@ -1,41 +1,58 @@ pub mod svg; use svg::*; +pub mod key; +use key::*; + use askama::Template; use derive_more::From; -use lazy_static::lazy_static; use std::{fs::OpenOptions, io::Write}; +use lazy_static::lazy_static; #[derive(Template)] #[template(path = "document.xml")] struct DocumentTemplate<'a> { dimensions: &'a DocumentDimensions, - keyboard: kle_serial::Keyboard, + box_size: SVGMeasure, + positions: Vec<(&'a Key<'a>, (SVGMeasure, SVGMeasure))>, } struct DocumentDimensions { width: SVGMeasure, height: SVGMeasure, - margin: SVGMeasure, -} - -fn kle_font_units(kle_font_units: &usize) -> SVGMeasure { - SVGMeasure::new((6 + kle_font_units * 2) as f64, SVGUnit::Pixel) -} - -lazy_static! { - static ref LETTER_LANDSCAPE: DocumentDimensions = DocumentDimensions { - width: SVGMeasure::new(11.0, SVGUnit::Inch), - height: SVGMeasure::new(8.5, SVGUnit::Inch), - margin: SVGMeasure::new(0.25, SVGUnit::Inch), - }; } #[derive(From, Debug)] enum Error { Io(std::io::Error), Template(askama::Error), - LayoutParse(serde_json::Error), +} + +fn positions<'a>( + keys: &'a Vec, + size: SVGMeasure, + margin: SVGMeasure, + padding: SVGMeasure, + dimensions: &DocumentDimensions, +) -> Vec<(&'a Key<'a>, (SVGMeasure, SVGMeasure))> { + let grid = size + padding; + let mut x = margin; + let mut y = margin; + let mut positions = Vec::with_capacity(keys.len()); + for key in keys { + if let Key::Break = key { + x = margin; + y = y + grid; + continue; + } + if x + grid > dimensions.width - margin { + x = margin; + y = y + grid; + } + positions.push((key, (x, y))); + x = x + size * key.width_mod() + padding; + } + positions } fn main() -> Result<(), Error> { @@ -44,10 +61,33 @@ fn main() -> Result<(), Error> { .truncate(true) .create(true) .open("output.svg")?; + let dimensions = DocumentDimensions { + width: SVGMeasure::new(8.5, SVGUnit::Inch), + height: SVGMeasure::new(11.0, SVGUnit::Inch), + }; + let box_size = SVGMeasure::new(14.0, SVGUnit::Millimeter); + let padding = SVGMeasure::new(2.5, SVGUnit::Millimeter); + let margin = SVGMeasure::new(0.25, SVGUnit::Inch); let document = DocumentTemplate { - dimensions: &LETTER_LANDSCAPE, - keyboard: serde_json::from_str(&std::fs::read_to_string("layout.json")?)?, + positions: positions(&KEYS, box_size, margin, padding, &dimensions), + dimensions: &dimensions, + box_size, }; write!(file, "{}", document.render()?)?; Ok(()) } + +lazy_static! { + static ref KEYS: Vec> = { + let mut keys = OYAYUBI.to_vec(); + keys.push(Key::Break); + keys.push(single("親指左", 3.0)); + keys.push(single("親指右", 3.0)); + keys.push(Key::Break); + keys.push(icon("assets/nixos.svg", 1.0)); + keys.push(icon("assets/playpause.svg", 1.0)); + keys.push(icon("assets/previous.svg", 1.0)); + keys.push(icon("assets/next.svg", 1.0)); + keys + }; +} \ No newline at end of file diff --git a/dyesub-tool/src/svg/measure.rs b/dyesub-tool/src/svg/measure.rs index e9c3afa..092c2a6 100644 --- a/dyesub-tool/src/svg/measure.rs +++ b/dyesub-tool/src/svg/measure.rs @@ -19,7 +19,7 @@ pub struct SVGMeasure { } impl SVGMeasure { - pub const fn new(measure: f64, unit: SVGUnit) -> Self { + pub fn new(measure: f64, unit: SVGUnit) -> Self { Self { measure, unit } } diff --git a/dyesub-tool/templates/document.xml b/dyesub-tool/templates/document.xml index be9847b..49a9758 100644 --- a/dyesub-tool/templates/document.xml +++ b/dyesub-tool/templates/document.xml @@ -4,63 +4,30 @@ - {% let u = crate::svg::SVGMeasure::new(14.0, crate::svg::SVGUnit::Millimeter) %} - {% let padding = crate::svg::SVGMeasure::new(2.5, crate::svg::SVGUnit::Millimeter) %} - {% let dy = "0.125em" %} - {% for key in keyboard.keys %} - {% let x = u * key.x + padding * key.x + dimensions.margin %} - {% let y = u * key.y + padding * key.y + dimensions.margin %} - {% let width = u * key.width %} - {% let height = u * key.height %} - - - - {# top-left #} - {% if let Some(legend) = key.legends[0] %} - {{ legend.text }} - {% endif %} - - {# top-center #} - {% if let Some(legend) = key.legends[1] %} - {{ legend.text }} - {% endif %} - - {# top-right #} - {% if let Some(legend) = key.legends[2] %} - {{ legend.text }} - {% endif %} - - {# middle-left #} - {% if let Some(legend) = key.legends[3] %} - {{ legend.text }} - {% endif %} - - {# middle-center #} - {% if let Some(legend) = key.legends[4] %} - {{ legend.text }} - {% endif %} - - {# middle-right #} - {% if let Some(legend) = key.legends[5] %} - {{ legend.text }} - {% endif %} - - {# bottom-left #} - {% if let Some(legend) = key.legends[6] %} - {{ legend.text }} - {% endif %} - - {# bottom-center #} - {% if let Some(legend) = key.legends[7] %} - {{ legend.text }} - {% endif %} - - {# bottom-right #} - {% if let Some(legend) = key.legends[8] %} - {{ legend.text }} - {% endif %} - - {# TODO 9-11 are side #} + {% for (key, (x, y)) in positions %} + {% let width = box_size * key.width_mod() %} + + + {% let dy = "0.125em" %} + {% match key %} + {% when crate::key::Key::Oyayubi with { latin, normal, shift, alt_shift } %} + {% let font_size = "0.45cm" %} + {% let latin_font_size = "0.4cm" %} + {% let alt_shift_font_size = "0.325cm" %} + {{ latin }} + {{ shift }} + {{ normal }} + {% if let Some(alt_shift) = alt_shift %} + {{ alt_shift }} + {% endif %} + {% when crate::key::Key::Single with { text, u } %} + {% let font_size = "0.5cm" %} + {{ text }} + {% when crate::key::Key::Icon with { icon_path, u } %} + {% let icon_width_mm = 7.5 %} + + {% when crate::key::Key::Break %} + {% endmatch %} {% endfor %} diff --git a/flake.nix b/flake.nix index dc99fc7..7abf022 100644 --- a/flake.nix +++ b/flake.nix @@ -51,7 +51,7 @@ Updating `cargoHash`: pname = "dyesub-tool"; version = "0.1.0"; buildAndTestSubdir = "dyesub-tool"; - cargoHash = "sha256-kZUTrejN4KVZ91CkpweLivwm9KaMT+fT6Ljq5Vy0Jik="; + cargoHash = "sha256-QlLyKDZZ+/bB4xBv0j9GoL6Ur3Okdskkazi4WlHhx6Y="; meta = meta // { description = "A tool for generating dye sublimation transfer sheet SVGs for Japanese thumb shift 拇指シフト keycaps."; };