//! Simple shapes export as SVG basic shapes (#4652): axis-aligned rectangles, circles and //! ellipses, straight lines, and polygons/polylines of straight segments. Everything else, and //! rectangles and ellipses whose dashes would start elsewhere, stays ``; the picture and the //! reimported geometry don't change. use vectorcraft_color::{Color, Paint}; use vectorcraft_doc::{Appearance, AppearanceItem, Dash, Document, FillLayer, Node, StrokeLayer}; use vectorcraft_geom::{Affine, PathData, Point, Rect, SubPath, shapes}; use vectorcraft_svg::{ExportOptions, export, import}; use vectorcraft_testkit::raster::{Image, assert_similar, render_artboard}; fn painted(dash: bool) -> Appearance { let mut st = StrokeLayer::new(Paint::solid(Color::rgb(0.1, 0.2, 0.6)), 3.0); if dash { st.dash = Some(Dash { pattern: vec![6.0, 4.0], offset: 0.0, align_corners: false }); } Appearance { items: vec![AppearanceItem::Fill(FillLayer::new(Paint::solid(Color::rgb(0.9, 0.5, 0.1)))), AppearanceItem::Stroke(st)], ..Default::default() } } fn doc(paths: Vec<(PathData, bool)>) -> Document { let mut d = Document::new(200.0, 200.0); let l = d.layers[0].id; for (p, dash) in paths { let n = Node::path(d.alloc_id(), p, painted(dash)); d.insert(Some(l), usize::MAX, n).unwrap(); } d } fn svg_of(p: PathData, dash: bool) -> String { export(&doc(vec![(p, dash)]), &ExportOptions::default()) } fn poly(pts: &[(f64, f64)], closed: bool) -> PathData { let pts: Vec = pts.iter().map(|&(x, y)| Point::new(x, y)).collect(); PathData::single(SubPath::polyline(&pts, closed)) } #[test] fn each_simple_shape_writes_its_element() { let cases = [ (shapes::rectangle(Rect::new(10.0, 20.0, 110.0, 70.0)), " Image { let tree = resvg::usvg::Tree::from_str(svg, &resvg::usvg::Options::default()).expect("parse"); let mut pm = resvg::tiny_skia::Pixmap::new(200, 200).unwrap(); pm.fill(resvg::tiny_skia::Color::WHITE); resvg::render(&tree, resvg::tiny_skia::Transform::identity(), &mut pm.as_mut()); Image { width: 200, height: 200, rgba: pm.data().to_vec() } } fn shapes_doc() -> Document { doc(vec![ (shapes::rectangle(Rect::new(10.0, 20.0, 110.0, 70.0)), false), (shapes::rectangle(Rect::new(120.0, 20.0, 190.0, 70.0)), true), (shapes::ellipse(Rect::new(10.0, 80.0, 50.0, 120.0)), false), (shapes::ellipse(Rect::new(60.0, 80.0, 140.0, 120.0)), false), (shapes::line(Point::new(150.0, 80.0), Point::new(190.0, 120.0)), true), (poly(&[(20.0, 185.0), (60.0, 185.0), (40.0, 135.0)], true), false), (poly(&[(80.0, 140.0), (120.0, 180.0), (160.0, 140.0)], false), true), ]) } #[test] fn shape_elements_render_like_the_canvas() { let d = shapes_doc(); let svg = export(&d, &ExportOptions::default()); assert!(!svg.contains(" 1e-3); assert!(!far, "{a:?} came back as {b:?}"); } }