From 958566468abb925cd45bfd6a9fcdf6346a9e07b1 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 31 Oct 2026 00:29:28 -0700 Subject: [PATCH] DXF export: dashed polylines continue their linetype around vertices A polyline with a linetype now sets group 70 bit 128, so the dash pattern runs on through its vertices instead of restarting at each corner. This applies to LWPOLYLINE and the R12 POLYLINE. --- crates/cad/src/scene.rs | 3 ++- crates/cad/src/tests.rs | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/cad/src/scene.rs b/crates/cad/src/scene.rs index a292d5a7f..34e69d6ed 100644 --- a/crates/cad/src/scene.rs +++ b/crates/cad/src/scene.rs @@ -872,7 +872,8 @@ impl<'a> Scene<'a> { let pts: Vec = pts.iter().map(|p| self.pt(*p)).collect(); let layer = self.layer.clone(); let h = self.handle(); - let flags = i64::from(closed); + // Bit 128: a linetype runs on through the vertices instead of restarting at each one. + let flags = i64::from(closed) | if style.linetype.is_some() { 128 } else { 0 }; if self.o.version.lwpolyline() { self.e.entity("LWPOLYLINE", h, fixed::MODEL_RECORD, &layer, style, "AcDbPolyline"); self.e.int(90, pts.len() as i64); diff --git a/crates/cad/src/tests.rs b/crates/cad/src/tests.rs index aff8489c4..f02047492 100644 --- a/crates/cad/src/tests.rs +++ b/crates/cad/src/tests.rs @@ -696,6 +696,30 @@ fn dashes_that_start_part_way_into_their_pattern_are_outlined() { assert_eq!(get(&entities(&editable)[0], 6), Some("DASHED1")); } +#[test] +fn dashed_polylines_continue_their_pattern_around_corners() { + let rect = |dash: Option| { + doc_with(|d| { + let mut n = path(d, shapes::rectangle(Rect::new(10.0, 10.0, 110.0, 60.0)), Paint::None, Paint::solid(Color::BLACK), 1.0); + if let Some(st) = n.appearance.stroke_mut() { + st.dash = dash.clone(); + } + vec![n] + }) + }; + let flags = |out: &DxfOutput| entities(out).first().and_then(|e| get(e, 70).map(str::to_string)); + // Group 70 bit 128 makes the linetype run on through the vertices instead of restarting + // at each one; a solid polyline keeps only its closed bit. + let dashed = rect(Some(Dash { pattern: vec![6.0, 3.0], offset: 0.0, align_corners: false })); + for o in [opts(&dashed), DxfOptions { alter_paths: true, ..opts(&dashed) }, DxfOptions { preserve: Preserve::Editability, ..opts(&dashed) }] { + assert_eq!(flags(&export(&dashed, &o).unwrap()).as_deref(), Some("129")); + } + let r12 = export(&dashed, &DxfOptions { version: DxfVersion::R12, ..opts(&dashed) }).unwrap(); + assert_eq!((kinds(&r12).first().map(String::as_str), flags(&r12).as_deref()), (Some("POLYLINE"), Some("129"))); + let solid = rect(None); + assert_eq!(flags(&export(&solid, &opts(&solid)).unwrap()).as_deref(), Some("1")); +} + fn text_doc(text: &str, size: f64) -> Document { doc_with(|d| { let style = CharStyle { size, fill: Paint::solid(Color::rgb(0.0, 0.5, 0.0)), ..CharStyle::default() };