From a5be18b693aeb466d871476803a3b44ff6a9cb62 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Wed, 28 Oct 2026 17:57:36 -0700 Subject: [PATCH] Save As .ai: name dots and corner-fitted dashes in the editing data's stroke warning Dotted strokes (zero-length dashes with round or projecting caps) and dashes fitted to corners are written as filled outlines in the editing data for other apps. The warning that lists the strokes written that way now names them. --- crates/eps/src/ai_editing/tests.rs | 20 ++++++++++++++++++++ crates/eps/src/ai_editing/writer.rs | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/eps/src/ai_editing/tests.rs b/crates/eps/src/ai_editing/tests.rs index e0d0b2d68..402e34f4d 100644 --- a/crates/eps/src/ai_editing/tests.rs +++ b/crates/eps/src/ai_editing/tests.rs @@ -387,6 +387,26 @@ fn the_palette_starts_with_registration() { assert_eq!(swatches(&read_back(&doc)), swatches(&doc)); } +#[test] +fn dotted_strokes_are_written_as_their_dots_with_a_warning() { + let mut doc = Document::new(200.0, 100.0); + let layer = doc.layers[0].id; + let mut stroke = StrokeLayer::new(solid(Color::rgb(0.0, 0.0, 0.0)), 4.0); + stroke.cap = LineCap::Round; + stroke.dash = Some(Dash { pattern: vec![0.0, 10.0], offset: 0.0, align_corners: false }); + let line = PathData::from_bezpath(&kurbo::BezPath::from_vec(vec![ + kurbo::PathEl::MoveTo((10.0, 50.0).into()), + kurbo::PathEl::LineTo((60.0, 50.0).into()), + ])); + let n = Node::path(doc.alloc_id(), line, Appearance { items: vec![AppearanceItem::Stroke(stroke)], ..Appearance::default() }); + doc.insert(Some(layer), usize::MAX, n).unwrap(); + let out = export_ai_editing(&doc, &opts()).unwrap(); + assert!(out.warnings.iter().any(|w| w.contains("dots")), "{:?}", out.warnings); + let text = program(&doc); + assert!(!text.contains("[0 10] 0 d"), "{text}"); + assert!(text.matches("\nf\n").count() >= 5, "a filled dot for each dash: {text}"); +} + #[test] fn hidden_layers_open_hidden() { let mut doc = sample(); diff --git a/crates/eps/src/ai_editing/writer.rs b/crates/eps/src/ai_editing/writer.rs index 39a19b4c1..24c0d57b8 100644 --- a/crates/eps/src/ai_editing/writer.rs +++ b/crates/eps/src/ai_editing/writer.rs @@ -32,7 +32,7 @@ pub(super) const CLIPPING: &str = pub(super) const IMAGES: &str = "images are written as their outlines filled with their average color in the editing data for other apps"; pub(super) const LIVE: &str = "symbols, blends, envelopes, meshes, repeats, placed documents and intertwines are written as their art in the editing data for other apps"; -const STROKES: &str = "strokes a plain line can't draw (inside or outside the path, variable width, gradients, patterns, arrowheads) are written as filled outlines, and brushed strokes as their brush's art, in the editing data for other apps"; +const STROKES: &str = "strokes a plain line can't draw (inside or outside the path, variable width, dots, dashes fitted to corners, gradients, patterns, arrowheads) are written as filled outlines, and brushed strokes as their brush's art, in the editing data for other apps"; pub(super) const TRANSPARENCY: &str = "transparency (opacity, blending modes, opacity masks) is left out of the editing data for other apps"; pub(super) const EFFECTS: &str = "live effects other than geometry effects are left out of the editing data for other apps"; const SWATCHES: &str = "gradient and pattern swatches are left out of the editing data for other apps";