generated from ElnuDev/rust-project
Compare commits
No commits in common. "78aae3de62abbb1821dd22812956977949882e86" and "d4c7f529558344c04848da6bccd404bc67534478" have entirely different histories.
78aae3de62
...
d4c7f52955
8 changed files with 31 additions and 214 deletions
79
Cargo.lock
generated
79
Cargo.lock
generated
|
@ -2,15 +2,6 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aho-corasick"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "askama"
|
name = "askama"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
@ -86,18 +77,8 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"lazy_static",
|
|
||||||
"regex",
|
|
||||||
"strum",
|
|
||||||
"strum_macros",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "heck"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humansize"
|
name = "humansize"
|
||||||
version = "2.1.3"
|
version = "2.1.3"
|
||||||
|
@ -107,12 +88,6 @@ dependencies = [
|
||||||
"libm",
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libm"
|
name = "libm"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
@ -190,35 +165,6 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex"
|
|
||||||
version = "1.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
|
|
||||||
dependencies = [
|
|
||||||
"aho-corasick",
|
|
||||||
"memchr",
|
|
||||||
"regex-automata",
|
|
||||||
"regex-syntax",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-automata"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
|
|
||||||
dependencies = [
|
|
||||||
"aho-corasick",
|
|
||||||
"memchr",
|
|
||||||
"regex-syntax",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.7.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -228,12 +174,6 @@ dependencies = [
|
||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustversion"
|
|
||||||
version = "1.0.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
|
@ -260,25 +200,6 @@ dependencies = [
|
||||||
"syn 2.0.28",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum"
|
|
||||||
version = "0.25.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum_macros"
|
|
||||||
version = "0.25.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059"
|
|
||||||
dependencies = [
|
|
||||||
"heck",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rustversion",
|
|
||||||
"syn 2.0.28",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
|
|
|
@ -6,7 +6,3 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
askama = "0.12.0"
|
askama = "0.12.0"
|
||||||
derive_more = "0.99.17"
|
derive_more = "0.99.17"
|
||||||
lazy_static = "1.4.0"
|
|
||||||
regex = "1.9.3"
|
|
||||||
strum = "0.25.0"
|
|
||||||
strum_macros = "0.25.2"
|
|
||||||
|
|
|
@ -8,12 +8,6 @@ use std::{fs::OpenOptions, io::Write};
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "document.xml")]
|
#[template(path = "document.xml")]
|
||||||
struct DocumentTemplate {
|
struct DocumentTemplate {
|
||||||
dimensions: DocumentDimensions,
|
|
||||||
box_size: SVGMeasure,
|
|
||||||
positions: Vec<(SVGMeasure, SVGMeasure)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DocumentDimensions {
|
|
||||||
width: SVGMeasure,
|
width: SVGMeasure,
|
||||||
height: SVGMeasure,
|
height: SVGMeasure,
|
||||||
}
|
}
|
||||||
|
@ -24,42 +18,16 @@ enum Error {
|
||||||
Template(askama::Error),
|
Template(askama::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn positions(
|
|
||||||
size: SVGMeasure,
|
|
||||||
padding: SVGMeasure,
|
|
||||||
dimensions: &DocumentDimensions,
|
|
||||||
count: u32,
|
|
||||||
) -> Vec<(SVGMeasure, SVGMeasure)> {
|
|
||||||
let grid = size + padding;
|
|
||||||
let row_count = ((dimensions.width - padding * 2.0) / grid) as u32;
|
|
||||||
(0..count)
|
|
||||||
.map(|i| {
|
|
||||||
(
|
|
||||||
grid * (i % row_count).into() + padding,
|
|
||||||
grid * (i / row_count).into() + padding,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.open("output.svg")?;
|
.open("output.svg")?;
|
||||||
let dimensions = DocumentDimensions {
|
let document = DocumentTemplate {
|
||||||
width: SVGMeasure::new(8.5, SVGUnit::Inch),
|
width: SVGMeasure::new(8.5, SVGUnit::Inch),
|
||||||
height: SVGMeasure::new(11.0, SVGUnit::Inch),
|
height: SVGMeasure::new(11.0, SVGUnit::Inch),
|
||||||
};
|
};
|
||||||
let box_size = SVGMeasure::new(14.0, SVGUnit::Millimeter);
|
|
||||||
let boxes = 54;
|
|
||||||
let padding = SVGMeasure::new(2.5, SVGUnit::Millimeter);
|
|
||||||
let document = DocumentTemplate {
|
|
||||||
positions: positions(box_size, padding, &dimensions, boxes),
|
|
||||||
dimensions,
|
|
||||||
box_size,
|
|
||||||
};
|
|
||||||
write!(file, "{}", document.render()?)?;
|
write!(file, "{}", document.render()?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
use super::SVGUnit;
|
use super::SVGUnit;
|
||||||
use derive_more::From;
|
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use regex::Regex;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::num::ParseFloatError;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
ops::{Add, Div, Mul, Rem, Sub},
|
ops::{Add, Div, Mul, Sub},
|
||||||
};
|
};
|
||||||
use strum::ParseError;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct SVGMeasure {
|
pub struct SVGMeasure {
|
||||||
|
@ -23,11 +16,11 @@ impl SVGMeasure {
|
||||||
Self { measure, unit }
|
Self { measure, unit }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_user_units(self) -> f64 {
|
fn to_user_units(&self) -> f64 {
|
||||||
self.measure * self.unit.to_user_units()
|
self.measure * self.unit.to_user_units()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_unit(self, unit: SVGUnit) -> Self {
|
fn to_unit(&self, unit: SVGUnit) -> Self {
|
||||||
SVGMeasure {
|
SVGMeasure {
|
||||||
measure: self.to_user_units() / unit.to_user_units(),
|
measure: self.to_user_units() / unit.to_user_units(),
|
||||||
unit,
|
unit,
|
||||||
|
@ -35,49 +28,15 @@ impl SVGMeasure {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(From, Debug)]
|
|
||||||
pub enum SVGUnitParseError {
|
|
||||||
ParseMeasure(ParseFloatError),
|
|
||||||
ParseUnit(ParseError),
|
|
||||||
Invalid,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for SVGMeasure {
|
|
||||||
type Err = SVGUnitParseError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
if s == "0" {
|
|
||||||
return Ok(SVGMeasure::new(0.0, SVGUnit::Pixel));
|
|
||||||
}
|
|
||||||
lazy_static! {
|
|
||||||
static ref RE: Regex = Regex::new(r"^([\d.]+)([a-zA-Z]+)$").unwrap();
|
|
||||||
}
|
|
||||||
if let Some(captures) = RE.captures(s) {
|
|
||||||
let measure = captures[1].parse::<f64>()?;
|
|
||||||
let unit = captures[2].parse::<SVGUnit>()?;
|
|
||||||
Ok(SVGMeasure::new(measure, unit))
|
|
||||||
} else {
|
|
||||||
Err(SVGUnitParseError::Invalid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const EQ_TOLERANCE: f64 = 0.00001;
|
const EQ_TOLERANCE: f64 = 0.00001;
|
||||||
|
|
||||||
impl PartialEq for SVGMeasure {
|
impl PartialEq for SVGMeasure {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
(self.to_user_units() - other.to_user_units()).abs() < EQ_TOLERANCE
|
(self.to_user_units() - other.to_user_units()).abs() < EQ_TOLERANCE
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for SVGMeasure {
|
fn ne(&self, other: &Self) -> bool {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
(self.to_user_units() - other.to_user_units()).abs() > EQ_TOLERANCE
|
||||||
Some(if self == other {
|
|
||||||
Ordering::Equal
|
|
||||||
} else if self.to_user_units() > other.to_user_units() {
|
|
||||||
Ordering::Greater
|
|
||||||
} else {
|
|
||||||
Ordering::Less
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,14 +73,6 @@ impl Mul<f64> for SVGMeasure {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div for SVGMeasure {
|
|
||||||
type Output = f64;
|
|
||||||
|
|
||||||
fn div(self, other: Self) -> Self::Output {
|
|
||||||
self.measure / other.to_unit(self.unit).measure
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Div<f64> for SVGMeasure {
|
impl Div<f64> for SVGMeasure {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
@ -130,12 +81,3 @@ impl Div<f64> for SVGMeasure {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rem for SVGMeasure {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn rem(mut self, other: Self) -> Self::Output {
|
|
||||||
self.measure %= other.to_unit(self.unit).measure;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use crate::svg::{SVGMeasure, SVGUnit};
|
use crate::svg::{SVGMeasure, SVGUnit};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -46,21 +44,3 @@ fn ne() {
|
||||||
let b = SVGMeasure::new(10.0, SVGUnit::Pixel);
|
let b = SVGMeasure::new(10.0, SVGUnit::Pixel);
|
||||||
assert_ne!(a, b);
|
assert_ne!(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cmp() {
|
|
||||||
let m_10cm = SVGMeasure::new(10.0, SVGUnit::Centimeter);
|
|
||||||
let m_5mm = SVGMeasure::new(5.0, SVGUnit::Millimeter);
|
|
||||||
assert!(m_10cm > m_5mm);
|
|
||||||
assert!(m_5mm < m_10cm);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn from_str() {
|
|
||||||
let m_10cm = SVGMeasure::new(10.0, SVGUnit::Centimeter);
|
|
||||||
let m_5mm = SVGMeasure::new(5.0, SVGUnit::Millimeter);
|
|
||||||
let m_0 = SVGMeasure::new(0.0, SVGUnit::Pixel);
|
|
||||||
assert_eq!(m_10cm, SVGMeasure::from_str("10cm").unwrap());
|
|
||||||
assert_eq!(m_5mm, SVGMeasure::from_str("5mm").unwrap());
|
|
||||||
assert_eq!(m_0, SVGMeasure::from_str("0").unwrap());
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,38 +1,50 @@
|
||||||
use strum_macros::{Display, EnumString, IntoStaticStr};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
/// https://oreillymedia.github.io/Using_SVG/guide/units.html
|
/// https://oreillymedia.github.io/Using_SVG/guide/units.html
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, EnumString, IntoStaticStr)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub enum SVGUnit {
|
pub enum SVGUnit {
|
||||||
/// Pixel units, directly equivalent to SVG user units.
|
/// Pixel units, directly equivalent to SVG user units.
|
||||||
#[strum(serialize = "px")]
|
|
||||||
Pixel,
|
Pixel,
|
||||||
/// Inches.
|
/// Inches.
|
||||||
#[strum(serialize = "in")]
|
|
||||||
Inch,
|
Inch,
|
||||||
/// Centimeters.
|
/// Centimeters.
|
||||||
#[strum(serialize = "cm")]
|
|
||||||
Centimeter,
|
Centimeter,
|
||||||
/// Millimeters.
|
/// Millimeters.
|
||||||
#[strum(serialize = "mm")]
|
|
||||||
Millimeter,
|
Millimeter,
|
||||||
/// Points.
|
/// Points.
|
||||||
#[strum(serialize = "pt")]
|
|
||||||
Point,
|
Point,
|
||||||
// Picas.
|
// Picas.
|
||||||
#[strum(serialize = "pc")]
|
|
||||||
Pica,
|
Pica,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SVGUnit {
|
impl SVGUnit {
|
||||||
pub const fn to_user_units(&self) -> f64 {
|
pub fn to_user_units(&self) -> f64 {
|
||||||
use SVGUnit::*;
|
use SVGUnit::*;
|
||||||
match self {
|
match self {
|
||||||
Pixel => 1.0,
|
Pixel => 1.0,
|
||||||
Inch => 96.0,
|
Inch => 96.0,
|
||||||
Centimeter => 37.795,
|
Centimeter => 37.795,
|
||||||
Millimeter => 3.7795,
|
Millimeter => 3.7795,
|
||||||
Point => 1.3333,
|
Point => 4.0 / 3.0, // 1.3333
|
||||||
Pica => 16.0,
|
Pica => 16.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for SVGUnit {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use SVGUnit::*;
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match &self {
|
||||||
|
Pixel => "px",
|
||||||
|
Inch => "in",
|
||||||
|
Centimeter => "cm",
|
||||||
|
Millimeter => "mm",
|
||||||
|
Point => "pt",
|
||||||
|
Pica => "pc",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<svg version="1.1"
|
<svg version="1.1"
|
||||||
width="{{ dimensions.width }}" height="{{ dimensions.height }}"
|
width="{{ width }}" height="{{ height }}"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
{% for (x, y) in positions %}
|
<rect width="100%" height="100%" fill="gray" />
|
||||||
<rect x="{{ x }}" y="{{ y }}" rx="2mm" width="{{ box_size }}" height="{{ box_size }}" fill="none" stroke="#cccccc" stroke-width="1pt" />
|
|
||||||
{% endfor %}
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 164 B |
|
@ -51,7 +51,7 @@ Updating `cargoHash`:
|
||||||
pname = "dyesub-tool";
|
pname = "dyesub-tool";
|
||||||
version = "0.1.0";
|
version = "0.1.0";
|
||||||
buildAndTestSubdir = "dyesub-tool";
|
buildAndTestSubdir = "dyesub-tool";
|
||||||
cargoHash = "sha256-QlLyKDZZ+/bB4xBv0j9GoL6Ur3Okdskkazi4WlHhx6Y=";
|
cargoHash = "sha256-owoTOMY/u7K3Y96FIHXMJeqILAOFR2wSYozzsT+0p64=";
|
||||||
meta = meta // {
|
meta = meta // {
|
||||||
description = "A tool for generating dye sublimation transfer sheet SVGs for Japanese thumb shift 拇指シフト keycaps.";
|
description = "A tool for generating dye sublimation transfer sheet SVGs for Japanese thumb shift 拇指シフト keycaps.";
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue