From 1eb7ec83aec7d34958e06a4e4a71ce27b0d3671d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=B3=D0=B4=D0=B0=20=D0=9C=2E=D0=93=2E?= Date: Mon, 12 Oct 2026 17:21:51 +0300 Subject: [PATCH] Text: draw a saved shrink scale as it is PowerPoint fits shrink-on-overflow text again only when the text changes, never when a file opens: it draws the saved fontScale/lnSpcReduction even where our metrics would call the text overflowing (trailing empty paragraphs at full size, substituted fonts). Shrinking further on open made saved decks text smaller than PowerPoints (74 % instead of 85 % on a real deck). With no saved scale, or once an edit has reset it, the text is fitted as before. --- crates/text/src/lib.rs | 5 +++++ crates/text/src/tests.rs | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/text/src/lib.rs b/crates/text/src/lib.rs index 684ed4a8..288c69fe 100644 --- a/crates/text/src/lib.rs +++ b/crates/text/src/lib.rs @@ -835,8 +835,13 @@ pub fn layout(ctx: &Ctx, shape: &Shape, body: &TextBody, opts: &Opts) -> TextLay _ => (1.0, 0.0), }; let mut l = layout_scaled(ctx, shape, body, &bp, opts, scale0, reduce0); + // A scale PowerPoint saved is drawn as it is: PowerPoint fits the text again only when it + // changes (and editing resets the saved scale), not when a file opens, even where our + // metrics would call it overflowing (trailing empty paragraphs, substituted fonts). + let saved = scale0 < 1.0 || reduce0 > 0.0; if let (AutoFit::Shrink { .. }, false) = (autofit, opts.no_shrink) && l.overflow + && !saved { // Binary search the largest scale that fits (steps like 90%, 80%… with line reduction). let (mut lo, mut hi) = (0.1_f64, scale0); diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs index fcba4645..6049ee1c 100644 --- a/crates/text/src/tests.rs +++ b/crates/text/src/tests.rs @@ -62,12 +62,16 @@ fn saved_shrink_scale_is_drawn() { sh.text.as_mut().unwrap().body.autofit = Some(AutoFit::Shrink { font_scale: 0.625, line_reduction: 0.2 }); let l = lay(&p, &sh, 600.0, 300.0); assert_eq!((l.font_scale, l.line_reduction), (0.625, 0.2)); - // Text that doesn't fit even at the saved scale shrinks further. + // Text our metrics find overflowing at the saved scale is still drawn at it, as PowerPoint + // draws it until the text changes; with no saved scale it shrinks to fit. let text = (0..30).map(|i| format!("Line number {i}")).collect::>().join("\n"); let (p, mut sh) = setup(&text, 600.0, 200.0); sh.text.as_mut().unwrap().body.autofit = Some(AutoFit::Shrink { font_scale: 0.9, line_reduction: 0.1 }); let l = lay(&p, &sh, 600.0, 200.0); - assert!(l.font_scale < 0.9 && l.line_reduction >= 0.1, "{} {}", l.font_scale, l.line_reduction); + assert_eq!((l.font_scale, l.line_reduction), (0.9, 0.1)); + sh.text.as_mut().unwrap().body.autofit = Some(AutoFit::Shrink { font_scale: 1.0, line_reduction: 0.0 }); + let l = lay(&p, &sh, 600.0, 200.0); + assert!(l.font_scale < 0.9, "{}", l.font_scale); // Nonsense saved values are ignored. let (p, mut sh) = setup("Short", 600.0, 300.0); sh.text.as_mut().unwrap().body.autofit = Some(AutoFit::Shrink { font_scale: f64::NAN, line_reduction: 5.0 });