diff --git a/keyset-drawing/src/svg.rs b/keyset-drawing/src/svg.rs index 45e8bc0..389c821 100644 --- a/keyset-drawing/src/svg.rs +++ b/keyset-drawing/src/svg.rs @@ -4,9 +4,24 @@ use svg::Document; use super::{Drawing, KeyDrawing, KeyPath}; -macro_rules! fmt_num { - ($fmt:literal, $($args:expr),*) => { - format!($fmt, $(($args * 1e5).round() / 1e5),*) +macro_rules! float { + ($arg:expr $(,)?) => { + format!("{}", float!(@round $arg)) + }; + ($arg0:expr, $($args:expr),+ $(,)?) => { + format!("{}{}", float!(@round $arg0), float!(@inner $($args),+)) + }; + (@inner $arg:expr $(,)?) => { + format_args!("{}", float!(@format $arg)) + }; + (@inner $arg0:expr, $($args:expr),+ $(,)?) => { + format_args!("{}{}", float!(@format $arg0), float!(@inner $($args),+)) + }; + (@format $arg:expr) => { + format_args!("{}{}", if $arg.is_sign_positive() { " " } else { "" }, float!(@round $arg)) + }; + (@round $arg:expr) => { + ($arg * 1e3).round() / 1e3 }; } @@ -15,12 +30,11 @@ pub fn draw(drawing: &Drawing) -> String { let view_box = drawing.bounds * DOT_PER_UNIT; // Use 1000 user units per key let document = Document::new() - .set("width", fmt_num!("{}mm", size.width)) - .set("height", fmt_num!("{}mm", size.height)) + .set("width", format!("{}mm", float!(size.width))) + .set("height", format!("{}mm", float!(size.height))) .set( "viewBox", - fmt_num!( - "{} {} {} {}", + float!( view_box.min.x, view_box.min.y, view_box.size().width, @@ -41,7 +55,7 @@ fn draw_key(key: &KeyDrawing) -> Group { let origin = key.origin * DOT_PER_UNIT; let group = Group::new().set( "transform", - fmt_num!("translate({},{})", origin.x, origin.y), + format!("translate({},{})", float!(origin.x), float!(origin.y)), ); key.paths.iter().map(draw_path).fold(group, Group::add) } @@ -51,13 +65,13 @@ fn draw_path(path: &KeyPath) -> SvgPath { .data .iter() .map(|el| match *el { - PathSegment::Move(p) => fmt_num!("M{} {}", p.x, p.y), - PathSegment::Line(d) => fmt_num!("l{} {}", d.x, d.y), + PathSegment::Move(p) => format!("M{}", float!(p.x, p.y)), + PathSegment::Line(d) => format!("l{}", float!(d.x, d.y)), PathSegment::CubicBezier(c1, c2, d) => { - fmt_num!("c{} {} {} {} {} {}", c1.x, c1.y, c2.x, c2.y, d.x, d.y) + format!("c{}", float!(c1.x, c1.y, c2.x, c2.y, d.x, d.y)) } // GRCOV_EXCL_START - no quads in example - PathSegment::QuadraticBezier(c1, d) => fmt_num!("q{} {} {} {}", c1.x, c1.y, d.x, d.y), + PathSegment::QuadraticBezier(c1, d) => format!("q{}", float!(c1.x, c1.y, d.x, d.y)), // GRCOV_EXCL_STOP PathSegment::Close => "z".into(), }) @@ -71,7 +85,7 @@ fn draw_path(path: &KeyPath) -> SvgPath { if let Some(outline) = path.outline { svg_path .set("stroke", format!("{:x}", outline.color)) - .set("stroke-width", fmt_num!("{}", outline.width.get())) + .set("stroke-width", float!(outline.width.get())) } else { svg_path.set("stroke", "none") } @@ -102,13 +116,13 @@ mod tests { r##" - - + + - - - - + + + + "## )