From da2704bb456e2e5b542d175ad20048b4bc52b623 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Thu, 8 Oct 2026 08:34:49 +0300 Subject: [PATCH] fix(mleader): text left of its landing attaches by its right edge The text was placed by its alignment rather than its attachment point, so text on the left of the landing ran over the leader. It now attaches by the attachment point, and putting the text on a side (on creation or by a grip) turns left- or right-justified text to read away from the leader. Fixes #1646 Co-Authored-By: Claude Opus 5.5 --- src/entities/multileader.rs | 34 +++++++++++++++++++++-------- src/modules/annotate/mleader_cmd.rs | 7 +----- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/entities/multileader.rs b/src/entities/multileader.rs index b6992403f..bf201f3cf 100644 --- a/src/entities/multileader.rs +++ b/src/entities/multileader.rs @@ -703,11 +703,7 @@ fn apply_grip( } else { old_sign }; - ml.context.text_attachment_point = if new_sign >= 0.0 { - codec::entities::multileader::TextAttachmentPointType::Left - } else { - codec::entities::multileader::TextAttachmentPointType::Right - }; + set_mleader_text_side(ml, new_sign >= 0.0); set_mleader_text_location(ml, target + axis * (new_sign * (dogleg + gap))); if let Some(root) = ml.context.leader_roots.first_mut() { @@ -2226,10 +2222,10 @@ impl MultiLeaderTess for MultiLeader { }; // The context's attachment point exists in every DWG version; // the entity-level copy only exists from R2010 on. - let h_anchor: f32 = match ctx.text_alignment { - TextAlignmentType::Left => 0.0, - TextAlignmentType::Center => 0.5, - TextAlignmentType::Right => 1.0, + let h_anchor: f32 = match ctx.text_attachment_point { + codec::entities::multileader::TextAttachmentPointType::Left => 0.0, + codec::entities::multileader::TextAttachmentPointType::Center => 0.5, + codec::entities::multileader::TextAttachmentPointType::Right => 1.0, }; // Pick the vertical-anchor attachment based on text_attachment_direction: // Horizontal — leader attaches left/right; use ml.text_left_attachment @@ -2715,3 +2711,23 @@ mod tests { ); } } + +/// Put the text on the right (`to_right`) or left of its landing: the text +/// block attaches by its near edge, and left- or right-justified text turns +/// to read away from the leader. Centred text stays centred. +pub(crate) fn set_mleader_text_side(ml: &mut MultiLeader, to_right: bool) { + use codec::entities::multileader::TextAttachmentPointType; + let (attachment, alignment) = if to_right { + (TextAttachmentPointType::Left, TextAlignmentType::Left) + } else { + (TextAttachmentPointType::Right, TextAlignmentType::Right) + }; + ml.text_attachment_point = attachment; + ml.context.text_attachment_point = attachment; + if ml.context.text_alignment != TextAlignmentType::Center { + ml.context.text_alignment = alignment; + } + if ml.text_alignment != TextAlignmentType::Center { + ml.text_alignment = alignment; + } +} diff --git a/src/modules/annotate/mleader_cmd.rs b/src/modules/annotate/mleader_cmd.rs index 20d2b98a8..8ab6913dc 100644 --- a/src/modules/annotate/mleader_cmd.rs +++ b/src/modules/annotate/mleader_cmd.rs @@ -693,12 +693,7 @@ fn build_mleader( let to_right = (elbow_pt - arrow_pt).dot(ux.as_dvec3()) >= 0.0; let sign = if to_right { 1.0 } else { -1.0 }; let landing = ux * (sign as f32); - ml.context.text_attachment_point = - if to_right { - codec::entities::multileader::TextAttachmentPointType::Left - } else { - codec::entities::multileader::TextAttachmentPointType::Right - }; + crate::entities::multileader::set_mleader_text_side(&mut ml, to_right); ml.context.text_rotation = (ux.y as f64).atan2(ux.x as f64); ml.context.text_direction = Vector3::new(ux.x as f64, ux.y as f64, 0.0);