mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 13:17:19 -06:00
M3.83: gradients within, along or across a stroke
The Gradient panel's Stroke buttons now work: with the Stroke proxy on a
linear or radial gradient they lay it within the stroke (placed on the
page, as before), along the path (start to end of each subpath) or across
it (left edge to right edge; inside/outside strokes span their visible
side). `paint.editGradient {stroke: true, strokeMode}` sets it (new art
too with nothing selected); `document.inspect` reports
strokeOptions.gradientMode. Model: StrokeLayer.gradient_mode (default
Within, not written).
Shared geometry in effects::stroke::gradient: ribs on the bisectors of
the flattened path (fans round sharp corners, widened under arrowheads,
following width profiles) cut slices each painted with a linear piece of
the gradient (Gradient::span). The canvas and raster export clip them to
the stroke's outline and arrowheads, grown a pixel and composited with
copy so there are no seams and translucent stops paint once. SVG and PDF
write the same slices clipped to the outline, with a warning (new
vectorcraft_svg::export_with_report). Outline Stroke and Expand make
gradient meshes clipped to the outline. Mesh quads now grow along their
edges so thin quads show no seams. Dashes, profiles and arrowheads keep
working in both modes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ccdb1b30f6
commit
025d758abe
@@ -459,7 +459,8 @@ pub(crate) fn with_transparency(d: &mut Document, mut n: Node, opacity: f32, ble
|
||||
|
||||
/// The art stroke `st` of a path (`path`, `rule`) paints, as fills: its brush art, or the
|
||||
/// outline of the stroke (as on the canvas) filled with the stroke's paint, opacity, blend mode
|
||||
/// and effects. `None` when it paints nothing.
|
||||
/// and effects (a gradient along or across the stroke: gradient meshes in a clip group shaped
|
||||
/// like the outline). `None` when it paints nothing.
|
||||
pub(crate) fn outlined_stroke(
|
||||
d: &mut Document,
|
||||
brushes: &[vectorcraft_brush::Brush],
|
||||
@@ -481,6 +482,18 @@ pub(crate) fn outlined_stroke(
|
||||
if outline.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if let Some(g) = st.path_gradient() {
|
||||
// A gradient along or across the stroke: gradient meshes clipped to its outline.
|
||||
let meshes = vectorcraft_render::effects::stroke::gradient_meshes(&path.to_bezpath(), rule, st, &g.gradient);
|
||||
let mut clip = shape_node(d, outline, None);
|
||||
super::object::as_clipping_path(&mut clip).ok()?;
|
||||
let meshes: Vec<Node> = meshes.into_iter().map(|m| Node::new(d.alloc_id(), NodeKind::Mesh(m))).collect();
|
||||
let children = std::iter::once(clip).chain(meshes).map(Arc::new).collect();
|
||||
let group = Node::new(d.alloc_id(), NodeKind::Group { children, clip: true });
|
||||
let mut art = with_transparency(d, group, st.opacity, st.blend);
|
||||
art.appearance.effects = st.effects.clone();
|
||||
return Some(art);
|
||||
}
|
||||
let mut n = shape_node(d, outline, None);
|
||||
let fill = vectorcraft_doc::appearance::FillLayer {
|
||||
opacity: st.opacity,
|
||||
|
||||
Reference in New Issue
Block a user