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();