From 7380241724f49d41c17b9871bacf8cee175af43d Mon Sep 17 00:00:00 2001 From: Hasan Date: Mon, 2 Nov 2026 21:30:30 +0500 Subject: [PATCH] M3: a snapshot uses the scale the page is drawn at (#5716) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review of #5761: the scale came from zoom × device pixels, without the 96/72 the viewer draws at, and was capped at 8, so a snapshot zoomed in held fewer pixels than the screen showed: 417 against 534 for 100 pt at 400%. It now takes the viewer's own render scale, and the tile limit is what stops it. The roadmap entry says when 300 ppi can't be reached. --- ROADMAP.md | 2 +- crates/ui-egui/src/canvas/zoom_snap.rs | 2 +- crates/ui-egui/tests/it/viewer.rs | 14 +++++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 7596bd5d3b..84dfb3f489 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -243,7 +243,7 @@ Ranked; detail and the full milestone table in [docs/roadmap.md](docs/roadmap.md - **2026-11-02 (M10, #5743):** macOS print jobs name their title and owner (`com.apple.print.JobInfo.PMJobName`, `PMJobOwner`), as the system print dialog does, because a Kyocera filter crashes on a job without them. Checked by a test and through `doc_print` against a stand-in `lp`; not yet on a physical printer. -- **2026-11-02 (M3, #5716):** A snapshot is drawn at 300 ppi, or at the zoom if that is finer, so one taken zoomed out stays readable. A choice of resolution and a selection that stays active remain. +- **2026-11-02 (M3, #5716):** A snapshot is drawn at 300 ppi, or at the zoom if that is finer, so one taken zoomed out stays readable; an area too large for one 4096-pixel tile comes out as fine as a tile allows (about 147 ppi for 2000 pt). A choice of resolution and a selection that stays active remain. - **2026-11-02 (M14, #5737, #5460):** Preferences can turn off the update check at start. It stays on by default, and Help ▸ Check for updates still asks. - **2026-11-01 (M7, #5657):** Header/footer, watermark and background additions and replacements stage the complete call before committing. Synthetic later-page failures preserve exact incremental bytes, object count, dirty state and allocation cursor; success controls retain other marks and shared/inherited resources. Estimates unchanged. diff --git a/crates/ui-egui/src/canvas/zoom_snap.rs b/crates/ui-egui/src/canvas/zoom_snap.rs index a23f85a6a8..93e0b13210 100644 --- a/crates/ui-egui/src/canvas/zoom_snap.rs +++ b/crates/ui-egui/src/canvas/zoom_snap.rs @@ -126,7 +126,7 @@ impl PdfCraftApp { let view = &self.views[index]; let doc = self.session.get(view.id).ok_or("no document")?; let ppp = self.ctx.as_ref().map_or(2.0, |c| c.pixels_per_point()); - let scale = snapshot_scale((view.zoom * ppp).clamp(0.5, 8.0), view_rect[2] - view_rect[0], view_rect[3] - view_rect[1]); + let scale = snapshot_scale(view.render_scale(ppp), view_rect[2] - view_rect[0], view_rect[3] - view_rect[1]); let tile = Tile { x: (view_rect[0] * scale).floor().max(0.0) as u32, y: (view_rect[1] * scale).floor().max(0.0) as u32, diff --git a/crates/ui-egui/tests/it/viewer.rs b/crates/ui-egui/tests/it/viewer.rs index 7ab88d5888..f2c812ce78 100644 --- a/crates/ui-egui/tests/it/viewer.rs +++ b/crates/ui-egui/tests/it/viewer.rs @@ -986,11 +986,15 @@ fn a_snapshot_keeps_its_resolution_when_zoomed_out() { let (_, _, px) = h.state().last_snapshot.clone().expect("a snapshot"); assert!(px.as_chunks::<4>().0.iter().any(|p| p[0] < 100), "the text is in it"); - // Zoomed in past the minimum, a snapshot still has what the screen shows. - h.state_mut().set_option("zoom", "800").unwrap(); - h.run_steps(2); - let (w, _) = h.state_mut().snapshot(i, 0, [15.0, 125.0, 180.0, 160.0]).expect("a snapshot"); - assert!(w > sizes[0].0, "{w}"); + // Zoomed in past the minimum, a snapshot has every pixel the screen shows, however far. + let ppp = h.ctx.pixels_per_point(); + for zoom in [400.0_f32, 1600.0] { + h.state_mut().set_option("zoom", &zoom.to_string()).unwrap(); + h.run_steps(2); + let (w, _) = h.state_mut().snapshot(i, 0, [15.0, 125.0, 180.0, 160.0]).expect("a snapshot"); + let on_screen = (165.0 * zoom / 100.0 * pdfcraft_ui_egui::canvas::PT * ppp).ceil() as u32; + assert!(w.abs_diff(on_screen) <= 1, "{w} pixels at {zoom}%, {on_screen} on screen"); + } } /// #5716: at 300 ppi this page is more than the renderer draws in one tile, which would cut off