Skip to content

Commit 71ff4c9

Browse files
authored
Update 'Solidify Stroke' to preserve the original fill (#3971)
* Update 'Solidify Stroke' to preserve the original fill * Efficiency improvements
1 parent 50a618a commit 71ff4c9

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

node-graph/nodes/vector/src/vector_nodes.rs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,14 +1110,19 @@ async fn offset_path(_: impl Ctx, content: Table<Vector>, distance: f64, join: S
11101110

11111111
#[node_macro::node(category("Vector: Modifier"), path(core_types::vector))]
11121112
async fn solidify_stroke(_: impl Ctx, content: Table<Vector>) -> Table<Vector> {
1113+
// TODO: Make this node support stroke align, which it currently ignores
1114+
11131115
content
11141116
.into_iter()
1115-
.map(|mut row| {
1116-
let vector = row.element;
1117+
.flat_map(|row| {
1118+
let mut vector = row.element;
1119+
let transform = row.transform;
1120+
let alpha_blending = row.alpha_blending;
1121+
let source_node_id = row.source_node_id;
11171122

11181123
let stroke = vector.style.stroke().clone().unwrap_or_default();
11191124
let bezpaths = vector.stroke_bezpath_iter();
1120-
let mut result = Vector::default();
1125+
let mut solidified_stroke = Vector::default();
11211126

11221127
// Taking the existing stroke data and passing it to kurbo::stroke to generate new fill paths.
11231128
let join = match stroke.join {
@@ -1133,6 +1138,7 @@ async fn solidify_stroke(_: impl Ctx, content: Table<Vector>) -> Table<Vector> {
11331138
let dash_offset = stroke.dash_offset;
11341139
let dash_pattern = stroke.dash_lengths;
11351140
let miter_limit = stroke.join_miter_limit;
1141+
let paint_order = stroke.paint_order;
11361142

11371143
let stroke_style = kurbo::Stroke::new(stroke.weight)
11381144
.with_caps(cap)
@@ -1153,17 +1159,38 @@ async fn solidify_stroke(_: impl Ctx, content: Table<Vector>) -> Table<Vector> {
11531159
solidified.apply_affine(Affine::new(stroke.transform.inverse().to_cols_array()));
11541160
}
11551161

1156-
result.append_bezpath(solidified);
1162+
solidified_stroke.append_bezpath(solidified);
11571163
}
11581164

1159-
// We set our fill to our stroke's color, then clear our stroke.
1165+
// We set the solidified stroke's fill to the stroke's color and without a stroke.
11601166
if let Some(stroke) = vector.style.stroke() {
1161-
result.style.set_fill(Fill::solid_or_none(stroke.color));
1162-
result.style.set_stroke(Stroke::default());
1167+
solidified_stroke.style.set_fill(Fill::solid_or_none(stroke.color));
11631168
}
11641169

1165-
row.element = result;
1166-
row
1170+
let stroke_row = TableRow {
1171+
element: solidified_stroke,
1172+
transform,
1173+
alpha_blending,
1174+
source_node_id,
1175+
};
1176+
1177+
// If the original vector has a fill, preserve it as a separate row with the stroke cleared.
1178+
let has_fill = !vector.style.fill().is_none();
1179+
let fill_row = has_fill.then(move || {
1180+
vector.style.clear_stroke();
1181+
TableRow {
1182+
element: vector,
1183+
transform,
1184+
alpha_blending,
1185+
source_node_id,
1186+
}
1187+
});
1188+
1189+
// Ordering based on the paint order. The first row in the table is rendered below the second.
1190+
match paint_order {
1191+
PaintOrder::StrokeAbove => fill_row.into_iter().chain(std::iter::once(stroke_row)).collect::<Vec<_>>(),
1192+
PaintOrder::StrokeBelow => std::iter::once(stroke_row).chain(fill_row).collect::<Vec<_>>(),
1193+
}
11671194
})
11681195
.collect()
11691196
}
@@ -1208,7 +1235,7 @@ async fn path_is_closed(
12081235
) -> bool {
12091236
content
12101237
.iter()
1211-
.flat_map(|row| row.element.stroke_bezpath_iter().map(|bezpath| bezpath.elements().last() == Some(&kurbo::PathEl::ClosePath)))
1238+
.flat_map(|row| row.element.build_stroke_path_iter().map(|(_, closed)| closed))
12121239
.nth(index.max(0.) as usize)
12131240
.unwrap_or(false)
12141241
}

0 commit comments

Comments
 (0)