Files
vectorcraft/crates/svg/tests/it/dash_align.rs
T
aiongg 8cc69ed45c CI: one test binary per crate, nextest, line tables only (#3855)
* CI: line tables only for workspace crates, no debug info for dependencies

* CI: one integration-test binary per crate

Each crate's tests/*.rs files become modules of tests/it/main.rs. Files that change
process-wide state (Color Settings, the font database, installed plug-ins, the working
directory), the fuzz sweeps and the test targets the Affinity corpus workflow names stay
their own binaries.

* Docs: name the integration tests' new paths

* CI: xtask test with nextest and doctests, one wasm check, clippy --keep-going

cargo xtask ci runs the tests with cargo nextest (cargo test when it is not installed),
builds them with --lib --bins --tests, runs the doctests as their own step, and checks
the wasm crates in one cargo check --keep-going call.
2026-10-23 21:36:10 -04:00

42 lines
1.9 KiB
Rust

//! Dashes fitted to corners export as the canvas's filled outlines (a dash array can't fit them);
//! exact dashes stay a `stroke-dasharray`. Checked by rendering the exported SVG with resvg.
use vectorcraft_color::{Color, Paint};
use vectorcraft_doc::{Appearance, AppearanceItem, Dash, Document, Node, StrokeLayer};
use vectorcraft_geom::{Rect, shapes};
use vectorcraft_svg::{ExportOptions, export};
use vectorcraft_testkit::raster::{Image, assert_similar, render_artboard};
fn rect_doc(align_corners: bool) -> Document {
let mut d = Document::new(140.0, 90.0);
let mut st = StrokeLayer::new(Paint::solid(Color::BLACK), 4.0);
st.dash = Some(Dash { pattern: vec![12.0, 6.0], offset: 0.0, align_corners });
let n = Node::path(
d.alloc_id(),
shapes::rectangle(Rect::new(20.0, 20.0, 120.0, 70.0)),
Appearance { items: vec![AppearanceItem::Stroke(st)], ..Default::default() },
);
let l = d.layers[0].id;
d.insert(Some(l), 0, n).unwrap();
d
}
/// The SVG rendered by resvg on white at 1 px/pt.
fn resvg_render(svg: &str, w: u32, h: u32) -> Image {
let tree = resvg::usvg::Tree::from_str(svg, &resvg::usvg::Options::default()).expect("parse");
let mut pm = resvg::tiny_skia::Pixmap::new(w, h).unwrap();
pm.fill(resvg::tiny_skia::Color::WHITE);
resvg::render(&tree, resvg::tiny_skia::Transform::identity(), &mut pm.as_mut());
Image { width: w, height: h, rgba: pm.data().to_vec() }
}
#[test]
fn fitted_dashes_export_as_outlines_that_render_like_the_canvas() {
let d = rect_doc(true);
let svg = export(&d, &ExportOptions::default());
assert!(!svg.contains("stroke-dasharray") && !svg.contains("stroke="), "{svg}");
assert_similar(&render_artboard(&d), &resvg_render(&svg, 140, 90), 24.0, 0.002);
// Exact dashes are still a dash array.
assert!(export(&rect_doc(false), &ExportOptions::default()).contains("stroke-dasharray=\"12 6\""));
}