#617: point joins equal to the layer's no longer count as point styles (SVG keeps a plain stroke)

This commit is contained in:
bflatastic
2026-10-17 13:45:16 +07:00
parent 6023d3547a
commit 7fe0770b9d
5 changed files with 31 additions and 7 deletions
+3 -3
View File
@@ -468,9 +468,9 @@ impl VectorNetwork {
start_dir(&self.outward(seg, at_a)?)
}
/// Whether any point has a stroke cap or join of its own.
pub fn has_point_styles(&self) -> bool {
self.vertices.iter().any(|v| v.cap.is_some() || v.join.is_some())
/// Whether any point has a stroke cap of its own or a join other than the layer's `layer_join`.
pub fn has_point_styles(&self, layer_join: StrokeJoin) -> bool {
self.vertices.iter().any(|v| v.cap.is_some() || v.join.is_some_and(|j| j != layer_join))
}
/// The fill path: every region's loops.
+1 -2
View File
@@ -20,8 +20,7 @@ impl Styled {
/// shortcut: dashed, variable-width and brush strokes keep the layer's caps and joins at every point; stroke them run by run too if asked for.
/// Joins equal to the layer do not require styled runs; stored overrides remain unchanged.
pub(crate) fn new(net: &VectorNetwork, props: &StrokeProps) -> Option<Styled> {
let styled = net.vertices.iter().any(|v| v.cap.is_some() || v.join.is_some_and(|join| join != props.join));
if !styled || !props.dashes.is_empty() || props.profile().is_some() || props.brush.is_some() {
if !net.has_point_styles(props.join) || !props.dashes.is_empty() || props.profile().is_some() || props.brush.is_some() {
return None;
}
let mut net = net.rounded().unwrap_or_else(|| net.clone());
+1 -1
View File
@@ -155,7 +155,7 @@ pub fn stroke_area(n: &Node, path: &BezPath, closed: bool) -> Arc<BezPath> {
props.dashes.len().hash(&mut h);
// Points' own caps and joins (vector networks).
let net = match &n.kind {
NodeKind::Vector { network } if network.has_point_styles() => Some(network),
NodeKind::Vector { network } if network.has_point_styles(props.join) => Some(network),
_ => None,
};
for v in net.map(|n| n.vertices.as_slice()).unwrap_or_default() {
+1 -1
View File
@@ -638,7 +638,7 @@ impl W<'_> {
|| k.brush.is_some()
|| k.cap_start.is_arrow()
|| k.cap_end.is_arrow()
|| matches!(&n.kind, NodeKind::Vector { network } if network.has_point_styles())
|| matches!(&n.kind, NodeKind::Vector { network } if network.has_point_styles(k.join))
|| !(w.is_finite() && w > 0.0)
{
return None;
+25
View File
@@ -115,3 +115,28 @@ fn text_run_fill_survives_live_text_export() {
assert!(svg.contains("#000000"), "{svg}");
assert!(svg.contains("fill=\"#00FF00\"") && svg.contains(">b</tspan>") && svg.contains(">a</tspan>"), "{svg}");
}
#[test]
fn point_joins_equal_to_the_layer_join_keep_a_plain_stroke() {
use figcraft_doc::{StrokeJoin, VectorNetwork};
use figcraft_geom::kurbo::Point;
let svg_with = |join: StrokeJoin| {
let mut network = VectorNetwork::from_points(&[Point::new(0.0, 0.0), Point::new(50.0, 50.0), Point::new(100.0, 0.0)], false);
for v in &mut network.vertices {
v.join = Some(StrokeJoin::Miter);
}
if let Some(v) = network.vertices.get_mut(1) {
v.join = Some(join);
}
let mut d = Document::new("t");
let p = d.first_page().unwrap();
let v = d.create(p, NodeKind::Vector { network }, "V", 0.0, 0.0, 100.0, 50.0).unwrap();
let n = d.get_mut(v).unwrap();
n.strokes = vec![Paint::solid(Color::from_hex("000000").unwrap())];
n.stroke.weight = 2.0;
n.stroke.join = StrokeJoin::Miter;
export_svg(&d, &[v], &SvgOptions::default()).unwrap()
};
assert!(svg_with(StrokeJoin::Miter).contains("stroke-width=\"2\""), "equal joins stay a stroke");
assert!(!svg_with(StrokeJoin::Round).contains("stroke-width="), "a differing join is drawn as an outline");
}