From 6eebec7df67e7b42118496e010d35d0bce1df15d Mon Sep 17 00:00:00 2001 From: Hamza Naveed <45464935+Hamza0101@users.noreply.github.com> Date: Thu, 12 Nov 2026 11:16:48 +0500 Subject: [PATCH] Decrease Font Size steps down one size at a time from any size (#2070) Ctrl+[ (and Cmd+Shift+,) shrank any size above 66 straight to 66: the step list stopped at 66, so the largest list size below 120 was 66. The list now holds PowerPoint's sizes up to 96, as the Font Size box already listed them, and above 96 shrink steps back 8 points at a time, as grow steps up: 120 -> 112 -> 104 -> 96 -> 88 -> 80 -> 72 -> 66. The Font Size box lists the same SIZES instead of adding its own tail. Fixes #2059 --- crates/engine/src/cmd/format/font.rs | 10 +++++++-- crates/engine/src/tests.rs | 31 ++++++++++++++++++++++++++++ crates/ui-egui/src/ribbon/home.rs | 2 +- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/crates/engine/src/cmd/format/font.rs b/crates/engine/src/cmd/format/font.rs index 5b5fd8eea..c977fcb6f 100644 --- a/crates/engine/src/cmd/format/font.rs +++ b/crates/engine/src/cmd/format/font.rs @@ -55,12 +55,18 @@ pub(super) fn size(s: &mut Session, p: &Value) -> Result { format_run(s, &move |r| r.size = Some(v)) } -/// PowerPoint's font size list (grow/shrink steps through it). -pub const SIZES: [f64; 20] = [8.0, 9.0, 10.0, 10.5, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 24.0, 28.0, 32.0, 36.0, 40.0, 44.0, 48.0, 54.0, 60.0, 66.0]; +/// PowerPoint's font size list, as the Font Size box lists it (grow/shrink steps through it). +pub const SIZES: [f64; 24] = + [8.0, 9.0, 10.0, 10.5, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 24.0, 28.0, 32.0, 36.0, 40.0, 44.0, 48.0, 54.0, 60.0, 66.0, 72.0, 80.0, 88.0, 96.0]; +/// Grow steps up the list, then 8 points at a time past its top; shrink steps back down the same +/// way. A size past the top used to shrink straight to 66 (#2059). fn step(cur: f64, up: bool) -> f64 { + let top = SIZES[SIZES.len() - 1]; if up { SIZES.iter().copied().find(|v| *v > cur + 0.01).unwrap_or((cur + 8.0).min(4000.0)) + } else if cur - 0.01 > top { + (cur - 8.0).max(top) } else { SIZES.iter().rev().copied().find(|v| *v < cur - 0.01).unwrap_or((cur - 1.0).max(1.0)) } diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 4f40b2dfb..d4939d043 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -6921,6 +6921,37 @@ fn master_body_placeholder_format_keeps_per_level_formatting() { assert_eq!(shown(&s), vec![Some(28.0), Some(24.0)]); } +/// #2059: Decrease Font Size (Ctrl+[, Cmd+Shift+,) steps down one size at a time from any size: +/// PowerPoint's list up to 96, then 8 points at a time above it, as Increase Font Size steps up. +/// A size above 66 used to shrink straight to 66. +#[test] +fn shrinking_a_large_font_steps_down_one_size_at_a_time() { + let mut s = session(); + let r = s.execute("shape.insert", &json!({"preset": "rect", "rect": [80.0, 80.0, 420.0, 160.0], "text": "Big"})).unwrap(); + let id = deckcraft_model::ShapeId(u32::try_from(r["id"].as_u64().unwrap()).unwrap()); + let size = |s: &Session| s.doc().unwrap().shape(id).unwrap().text.as_ref().unwrap().paragraphs[0].runs[0].props.size; + s.execute("format.size", &json!({"size": 120})).unwrap(); + let mut down = vec![]; + for _ in 0..9 { + s.execute("format.shrink", &json!({})).unwrap(); + down.push(size(&s).unwrap()); + } + assert_eq!(down, [112.0, 104.0, 96.0, 88.0, 80.0, 72.0, 66.0, 60.0, 54.0]); + let mut up = vec![]; + for _ in 0..7 { + s.execute("format.grow", &json!({})).unwrap(); + up.push(size(&s).unwrap()); + } + assert_eq!(up, [60.0, 66.0, 72.0, 80.0, 88.0, 96.0, 104.0]); + // A size between list steps goes to the next one down, and one past the top steps 8 at most. + s.execute("format.size", &json!({"size": 99})).unwrap(); + s.execute("format.shrink", &json!({})).unwrap(); + assert_eq!(size(&s), Some(96.0)); + s.execute("format.size", &json!({"size": 150})).unwrap(); + s.execute("format.shrink", &json!({})).unwrap(); + assert_eq!(size(&s), Some(142.0)); +} + /// A shape named many times in one edit is edited once and not copied per mention. #[test] fn repeated_target_ids_edit_the_shape_once() { diff --git a/crates/ui-egui/src/ribbon/home.rs b/crates/ui-egui/src/ribbon/home.rs index 267f161d3..78dc637f7 100644 --- a/crates/ui-egui/src/ribbon/home.rs +++ b/crates/ui-egui/src/ribbon/home.rs @@ -197,7 +197,7 @@ fn font_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { }); let size_text = size.map(|s| widgets::fmt_num(s, "")).unwrap_or_default(); dropdown(ui, "Font size", &size_text, 52.0, en, |ui| { - for s in deckcraft_engine::cmd::format::SIZES.iter().chain([72.0, 80.0, 88.0, 96.0].iter()) { + for s in deckcraft_engine::cmd::format::SIZES.iter() { if ui.button(widgets::fmt_num(*s, "")).clicked() { run(app, "format.size", json!({"size": s})); ui.close();