From faf85f5af9eafaa27bccf45187bf4762c47b8de6 Mon Sep 17 00:00:00 2001 From: FredApps <153173854+FredApps@users.noreply.github.com> Date: Sun, 1 Nov 2026 14:50:40 +0100 Subject: [PATCH] fix(text): apply explicit sizes and preserve script characters An explicit size commit normalizes mixed-size selections even when the value matches the displayed size. Caret-only script commands format the whole draft. Mathematical minus uses reversible Unicode forms and ASCII hyphen-minus remains unchanged. Correct the applied-selection comment and document the character policy in parity and the tool. Co-Authored-By: Codex GPT-6.1 --- crates/automation/src/tools.rs | 2 +- crates/engine/src/text_script.rs | 23 +++++++---- crates/ui-egui/src/panels/edit.rs | 3 ++ crates/ui-egui/src/panels/format_text_ui.rs | 2 + crates/ui-egui/src/tools/edit_text_ui.rs | 46 +++++++++++++++++++-- parity/acrobat-features.toml | 2 +- 6 files changed, 64 insertions(+), 14 deletions(-) diff --git a/crates/automation/src/tools.rs b/crates/automation/src/tools.rs index 12d8715872..6d60a07cc9 100644 --- a/crates/automation/src/tools.rs +++ b/crates/automation/src/tools.rs @@ -1439,7 +1439,7 @@ pub fn tools() -> Vec { "scale": { "type": "number", "description": "Horizontal scale in percent." } }), &["doc", "page"], )), - t("text_script", "Superscript or subscript", "Format text ▸ Superscript or Subscript on one paragraph (paragraph, from text_paragraphs), or on range [start, end): UTF-8 byte offsets of its editor_text. The characters take the Unicode superscript or subscript forms (2 → ², 2 → ₂; the font must have those glyphs, and extracted text contains them); text already in that script goes back to plain characters. Characters Unicode has no such form for (q, a space) stay as they are and don't stop a second call toggling back. The paragraph is then rewritten as text_edit rewrites it, with the same result fields. Refused when no character would change. Undoable.") + t("text_script", "Superscript or subscript", "Format text ▸ Superscript or Subscript on one paragraph (paragraph, from text_paragraphs), or on range [start, end): UTF-8 byte offsets of its editor_text. The characters take the Unicode superscript or subscript forms (2 → ², 2 → ₂; the font must have those glyphs, and extracted text contains them); text already in that script goes back to plain characters. Characters Unicode has no such form for (q, a space) stay as they are and don't stop a second call toggling back. The paragraph is then rewritten as text_edit rewrites it, with the same result fields. Refused when no character would change. Undoable. Mathematical minus U+2212 has a reversible form; ASCII hyphen-minus stays unchanged.") .cmd("edit.edit_text") .with(schema( json!({ "doc": doc(), "page": { "type": "integer", "minimum": 1 }, "paragraph": { "type": "integer", "minimum": 1 }, diff --git a/crates/engine/src/text_script.rs b/crates/engine/src/text_script.rs index f1f72a1681..268fca3d21 100644 --- a/crates/engine/src/text_script.rs +++ b/crates/engine/src/text_script.rs @@ -27,7 +27,7 @@ const SUPERSCRIPT: &[(char, char)] = &[ ('8', '⁸'), ('9', '⁹'), ('+', '⁺'), - ('-', '⁻'), + ('−', '⁻'), ('=', '⁼'), ('(', '⁽'), (')', '⁾'), @@ -90,7 +90,7 @@ const SUBSCRIPT: &[(char, char)] = &[ ('8', '₈'), ('9', '₉'), ('+', '₊'), - ('-', '₋'), + ('−', '₋'), ('=', '₌'), ('(', '₍'), (')', '₎'), @@ -121,10 +121,9 @@ impl Script { } } - /// `c` raised or lowered, or `None` when Unicode has no such form for it. The minus sign - /// (U+2212) takes the hyphen-minus's form. + /// `c` raised or lowered, or `None` when Unicode has no distinct reversible form for it. + /// Mathematical minus U+2212 has a form; ASCII hyphen-minus stays unchanged to avoid a lossy collision. pub fn form(self, c: char) -> Option { - let c = if c == '−' { '-' } else { c }; self.pairs().iter().find(|(plain, _)| *plain == c).map(|&(_, form)| form) } @@ -195,9 +194,17 @@ mod tests { assert_eq!(toggle(&raised, None, script).unwrap().0, s, "{script:?} {plain}"); } } - // The minus sign takes the hyphen's form. - assert_eq!(toggle("−", None, Script::Super).unwrap().0, "⁻"); - assert_eq!(toggle("−", None, Script::Sub).unwrap().0, "₋"); + assert_eq!(toggle("-", None, Script::Super), None); + assert_eq!(toggle("-", None, Script::Sub), None); + } + + #[test] + fn review_script_round_trips_preserve_both_minus_characters() { + for script in [Script::Super, Script::Sub] { + let text = "−2 -3"; + let once = toggle(text, None, script).unwrap().0; + assert_eq!(toggle(&once, None, script).unwrap().0, text); + } } #[test] diff --git a/crates/ui-egui/src/panels/edit.rs b/crates/ui-egui/src/panels/edit.rs index 100b0cc11b..2ba86ee5f5 100644 --- a/crates/ui-egui/src/panels/edit.rs +++ b/crates/ui-egui/src/panels/edit.rs @@ -280,6 +280,9 @@ fn format_section(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) { Fonts { sources: Some(&sources), shown, mixed_size }, Some(paragraphs), ); + if out.size_committed { + ed.choose_size(ed.look.size); + } let mut changed = out.changed; if let Some(script) = out.script { changed |= crate::edit_text_ui::toggle_script(&mut ed.text, &mut ed.selection, script); diff --git a/crates/ui-egui/src/panels/format_text_ui.rs b/crates/ui-egui/src/panels/format_text_ui.rs index eb2979bff6..e3d4463607 100644 --- a/crates/ui-egui/src/panels/format_text_ui.rs +++ b/crates/ui-egui/src/panels/format_text_ui.rs @@ -87,6 +87,7 @@ impl Paragraphs<'_> { #[derive(Default)] pub(crate) struct Outcome { pub changed: bool, + pub size_committed: bool, pub font: Option, /// Superscript or Subscript was clicked, for the selected paragraphs' text. pub script: Option