From c5c5ba1b60d19c5b8b21ae48839a45e63ee2a774 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Fri, 1 May 2026 11:48:06 +0300 Subject: [PATCH] fix: correct MTEXT line spacing and preserve blank paragraph separators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Line spacing: DXF code 44 (line_spacing_factor) is a multiplier on AutoCAD's default baseline-to-baseline distance of 5/3 × text_height. The renderer was using factor × 1.0 instead of factor × 1.667, making all MTEXT appear cramped. Blank paragraphs: split_mtext_lines was filtering out empty strings, so \\P\\P (double paragraph break used to separate sections) was silently collapsed. Empty lines in the middle of the block are now preserved; only leading/trailing blank lines are stripped. Co-Authored-By: Claude Sonnet 4.6 --- src/entities/mtext.rs | 5 ++++- src/entities/text_support.rs | 10 +++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/entities/mtext.rs b/src/entities/mtext.rs index f80c751ff..76131b70f 100644 --- a/src/entities/mtext.rs +++ b/src/entities/mtext.rs @@ -99,7 +99,10 @@ fn to_truck(t: &MText, document: &acadrust::CadDocument) -> TruckEntity { } else { 1.0 }; - let line_h = t.height as f32 * ls_factor * font.line_spacing; + // AutoCAD DXF code 44 is a multiplier on the *default* baseline-to-baseline + // distance, which is 5/3 × text_height (≈ 1.667). factor = 1.0 → single + // spacing, factor = 2.0 → double spacing, etc. + let line_h = t.height as f32 * ls_factor * (5.0 / 3.0) * font.line_spacing; let total_h = line_h * n_lines; let v_offset = match t.attachment_point { AttachmentPoint::TopLeft | AttachmentPoint::TopCenter | AttachmentPoint::TopRight => 0.0, diff --git a/src/entities/text_support.rs b/src/entities/text_support.rs index 067cf07e5..4f764baaa 100644 --- a/src/entities/text_support.rs +++ b/src/entities/text_support.rs @@ -206,10 +206,14 @@ pub fn strip_mtext_codes(s: &str) -> String { } pub fn split_mtext_lines(s: &str) -> Vec { - s.split('\n') + let lines: Vec = s.split('\n') .map(|l| l.trim().to_string()) - .filter(|l| !l.is_empty()) - .collect() + .collect(); + // Drop leading and trailing blank lines, but preserve blank lines in the + // middle — they are intentional paragraph separators (\\P\\P in MTEXT). + let start = lines.iter().position(|l| !l.is_empty()).unwrap_or(0); + let end = lines.iter().rposition(|l| !l.is_empty()).map(|i| i + 1).unwrap_or(0); + lines[start..end].to_vec() } /// Measure the advance width of an MText line (after strip_mtext_codes), correctly