diff --git a/crates/engine/src/cmd/buildcmds.rs b/crates/engine/src/cmd/buildcmds.rs index 9e457212ad..13b7a3bd83 100644 --- a/crates/engine/src/cmd/buildcmds.rs +++ b/crates/engine/src/cmd/buildcmds.rs @@ -471,10 +471,11 @@ impl SourceStyle { /// How far, in points, a place on an edge may be from its source path and still be on it. const ON_SOURCE: f64 = 0.05; -/// Does stroke row `i` have settings that depend on where along its path a piece of it lies: -/// dashes, arrowheads, a width profile or a brush? +/// Does stroke row `i` have settings that depend on where along its path a piece of it lies or +/// which way it runs: dashes, arrowheads, a width profile, a brush, or a gradient along or across +/// the stroke? fn depends_on_place(i: &AppearanceItem) -> bool { - matches!(i, AppearanceItem::Stroke(s) if s.dash.is_some() || s.start_arrow.is_some() || s.end_arrow.is_some() || s.profile.is_some() || s.brush.is_some()) + matches!(i, AppearanceItem::Stroke(s) if s.dash.is_some() || s.start_arrow.is_some() || s.end_arrow.is_some() || s.profile.is_some() || s.brush.is_some() || s.gradient_mode != vectorcraft_doc::StrokeGradientMode::Within) } /// One subpath's segments with the length along it where each starts, then its whole length, and diff --git a/crates/engine/src/tests/build.rs b/crates/engine/src/tests/build.rs index 8fae2eadd4..0614f63658 100644 --- a/crates/engine/src/tests/build.rs +++ b/crates/engine/src/tests/build.rs @@ -2753,6 +2753,37 @@ fn live_paint_make_fits_dashes_and_arrowheads_to_each_edge() { assert_eq!(edges, vec![rows]); } +/// When Make cuts a stroke whose only setting that depends on direction is a gradient along or +/// across it, each edge runs the way its source path does, so the gradient keeps its direction. +#[test] +fn live_paint_make_keeps_the_direction_of_gradient_strokes() { + use vectorcraft_doc::StrokeGradientMode; + for mode in [StrokeGradientMode::Along, StrokeGradientMode::Across] { + for (x0, x1) in [(-20.0, 120.0), (120.0, -20.0)] { + let mut s = session(); + let a = rect(&mut s, 0.0, 0.0, 100.0, 100.0); + let l = line(&mut s, (x0, 50.0), (x1, 50.0)); + let gradient = Paint::Gradient(Box::new(vectorcraft_color::GradientPaint::new(vectorcraft_color::Gradient::default()))); + set_rows(&mut s, l, vec![stroke_row(gradient, 2.0, |st| st.gradient_mode = mode)]); + s.execute("select.set", &json!({"ids": [a.0, l.0]})).unwrap(); + let g = NodeId(s.execute("livePaint.make", &json!({})).unwrap()["id"].as_u64().unwrap()); + let pieces: Vec<(f64, f64)> = vectorcraft_tools::builder::edges(&node(&s, g)) + .iter() + .filter_map(|e| { + e.appearance.stroke().filter(|st| st.gradient_mode == mode)?; + let sp = e.path_data()?.subpaths.first()?; + Some((sp.anchors.first()?.p.x, sp.anchors.last()?.p.x)) + }) + .collect(); + assert_eq!(pieces.len(), 3, "{mode:?}, from {x0}"); + assert!( + pieces.iter().all(|&(p, q)| (q - p).signum() == (x1 - x0).signum()), + "{mode:?}, from {x0}: each piece runs the way the line does: {pieces:?}" + ); + } + } +} + /// Make gives each face every fill row of its source that draws, in order and with their /// opacity, blending mode, overprint and effects, and the source's gradients keep their fit on /// the source; Expand keeps the rows, and Undo and Redo bring the group back with them.