From fc5063c38dd7632cd9be592d71dfa167cb046bb6 Mon Sep 17 00:00:00 2001 From: rabis <340973947+rabis7575@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:10:12 +0200 Subject: [PATCH] #1899: keep at least 0.5% of a cropped axis, so nothing shown is culled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With 0.1% the whole source of a 4000 pt frame spanned up to 4,000,000 pt, past the ±1,000,000 pt limit Picture::place uses to leave out items far off the page, so a metafile cropped that narrow lost what the crop shows. At 0.5% it spans at most 800,000 pt (CodeRabbit on #3247). Co-Authored-By: Claude Opus 5.5 --- crates/metafile/src/place.rs | 12 +++++++----- crates/metafile/src/tests.rs | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/crates/metafile/src/place.rs b/crates/metafile/src/place.rs index aad4b7393..d1f4d1983 100644 --- a/crates/metafile/src/place.rs +++ b/crates/metafile/src/place.rs @@ -11,14 +11,16 @@ pub const MAX_BITMAP_SIDE: u32 = 30_000; const MAX_COORD: f64 = 1e6; /// Smallest placed bitmap side (target units), so the stretch onto it is never singular. const MIN_BITMAP_SIDE: f64 = 1e-6; -/// The least of a source axis a crop keeps (0.1%). Files crop pictures to slivers (a header bar -/// that is 2.7% of a page-sized metafile, #1899); this only keeps the stretch finite. -const MIN_VISIBLE: f64 = 0.001; +/// The least of a source axis a crop keeps (0.5%). Files crop pictures to slivers (a header bar +/// that is 2.7% of a page-sized metafile, #1899). Layout makes a picture's frame at most 4000 pt +/// a side, so the whole source then spans at most 800,000 pt: what it covers stays inside +/// `MAX_COORD` and is never left out as far off the page. +const MIN_VISIBLE: f64 = 0.005; /// The part of a picture's source that `crop` (left, top, right, bottom fractions of the source) /// keeps, as fractions of the source: [left, top, width, height], bitmap or metafile alike. Each -/// side is taken as 0–1 (junk as 0). When the two sides of an axis leave less than 0.1% of it, -/// the left (top) side stands and 0.1% shows. +/// side is taken as 0–1 (junk as 0). When the two sides of an axis leave less than 0.5% of it, +/// the left (top) side stands and 0.5% shows. pub fn crop_window(crop: [f32; 4]) -> [f64; 4] { let [l, t, r, b] = crop.map(|v| if v.is_finite() { f64::from(v.clamp(0.0, 1.0)) } else { 0.0 }); let axis = |lo: f64, hi: f64| { diff --git a/crates/metafile/src/tests.rs b/crates/metafile/src/tests.rs index 9295d4c1b..f67840f88 100644 --- a/crates/metafile/src/tests.rs +++ b/crates/metafile/src/tests.rs @@ -909,6 +909,25 @@ fn crop_window_keeps_a_sliver_and_stays_finite() { } } +/// The narrowest crop on the largest frame layout makes (4000 pt, far down a 22-inch page) still +/// places the source's content: none of it is left out as far off the page. +#[test] +fn the_narrowest_crop_on_the_largest_frame_keeps_its_content() { + let pic = crate::Picture { + width: 100.0, + height: 100.0, + items: vec![ + Item::Bitmap { rect: [0.0, 0.0, 100.0, 100.0], width: 1, height: 1, rgba: vec![255; 4] }, + Item::Path { segs: vec![Seg::Move(0.0, 0.0), Seg::Line(100.0, 100.0)], fill: None, stroke: Some(([0, 0, 0, 255], 1.0)), even_odd: false }, + ], + }; + let frame = kurbo::Rect::new(1584.0, 1584.0, 5584.0, 5584.0); + // The last sliver, the first sliver, and sides that overlap. + for crop in [[1.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 1.0], [0.9999, 0.6, 0.5, 0.9999]] { + assert_eq!(pic.place(frame, crop).len(), 2, "{crop:?}"); + } +} + #[test] fn place_keeps_only_finite_bounded_bitmaps_with_area() { let bitmap = |rect: [f32; 4]| Item::Bitmap { rect, width: 1, height: 1, rgba: vec![0; 4] };