From 1709d41e4f949031ab990442256602afb360f08c Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 7 Jul 2026 01:15:36 +0300 Subject: [PATCH] refactor(text): parse single-line ATTRIB text via acadrust MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Route single-line attribute text through the same acad_text_encode path TEXT uses (acadrust parse_plain_text, re-encoded for the stroke tessellator). Multi-line attributes already flow through layout_mtext (acadrust). No visible change — attribute text with %% codes rendered correctly before via the local tokenizer; this shares the one parser. TOLERANCE cells and complex-linetype text still use the local tokenizer (specialized paths that rarely carry %% codes). Co-Authored-By: Claude Opus 4.8 --- src/entities/attribute.rs | 5 ++++- src/entities/text.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/entities/attribute.rs b/src/entities/attribute.rs index 0485905db..c0d7c51b9 100644 --- a/src/entities/attribute.rs +++ b/src/entities/attribute.rs @@ -278,6 +278,9 @@ fn build_attr_truck(input: AttrTextInputs<'_>, document: &acadrust::CadDocument) anchor_f64[0] - (anchor_local_x as f64 * cos_r - local_y_for_line as f64 * sin_r), anchor_f64[1] - (anchor_local_x as f64 * sin_r + local_y_for_line as f64 * cos_r), ]; + // Parse `%%` codes through acadrust (same as TEXT), re-encoded for the + // stroke tessellator, so attribute text shares the one parser. + let encoded = crate::entities::text::acad_text_encode(line); let (strokes, fill_tris) = lff::tessellate_text_ex( [0.0, 0.0], input.height as f32, @@ -285,7 +288,7 @@ fn build_attr_truck(input: AttrTextInputs<'_>, document: &acadrust::CadDocument) width_factor, oblique_angle, &resolved.font_name, - line, + &encoded, ); strokes_all.push(TextStroke { strokes, diff --git a/src/entities/text.rs b/src/entities/text.rs index 4fc2ba8ad..5df593e04 100644 --- a/src/entities/text.rs +++ b/src/entities/text.rs @@ -71,7 +71,7 @@ pub struct TextPlacement { /// inline grammar: specials arrive resolved to Unicode, and `%%u`/`%%o` /// underline/overline become `\L…\l` / `\O…\o` decoration markers. This keeps /// TEXT parsing in acadrust rather than OCS's own tokenizer. -fn acad_text_encode(value: &str) -> String { +pub(crate) fn acad_text_encode(value: &str) -> String { use acadrust::entities::mtext_format::parse_plain_text; let doc = parse_plain_text(value); let mut out = String::new();