Let a zoomed view fill the viewport rather than keep the photograph's shape

The view was the same fraction of each axis, so it kept the frame's
aspect at every zoom: a portrait zoomed on a landscape screen stayed a
portrait strip with the screen's sides empty. Each axis now shows as
much of the frame as the viewport holds at that magnification, capped
at the whole frame, and the render is fitted to the viewed region
rather than to the frame. A redraw re-cuts a zoomed view about its
centre when the viewport or the crop changes shape.
This commit is contained in:
2026-10-02 22:29:48 -04:00
parent d5c93ae795
commit 0b06e31bf3
6 changed files with 239 additions and 71 deletions
+12 -5
View File
@@ -108,21 +108,28 @@ pub(super) fn shows_source_pixels(magnification: f64) -> bool {
/// pixels an export would have, and leaves the enlargement to it, which draws
/// them nearest-neighbour; it is also a fraction of the shading.
///
/// Below 1:1 this is [`fit`] of the whole frame, as it always was: the view
/// rect shrinking while the target keeps its size is how a zoom short of 1:1
/// gains detail. The two branches meet at 1:1, where both are the viewport.
/// Below 1:1 this is [`fit`] of the *viewed region*: the view rect shrinking
/// while the target keeps its size is how a zoom short of 1:1 gains detail.
/// The region rather than the whole frame, because a zoomed view takes the
/// viewport's shape (see `framing::view_extents`), and a render in the
/// frame's shape would letterbox it straight back. The two branches meet at
/// 1:1, where both are the viewport.
pub(super) fn render_size(
framed: (u32, u32),
view: (f32, f32),
viewport: (u32, u32),
) -> (u32, u32) {
if framed.0 == 0 || framed.1 == 0 || magnification(framed, view, viewport) < 1.0 {
if framed.0 == 0 || framed.1 == 0 {
return fit(framed.0, framed.1, viewport.0.max(1), viewport.1.max(1));
}
let behind = |edge: u32, fraction: f32| {
((f64::from(edge) * f64::from(fraction.clamp(f32::EPSILON, 1.0))).round() as u32).max(1)
};
(behind(framed.0, view.0), behind(framed.1, view.1))
let region = (behind(framed.0, view.0), behind(framed.1, view.1));
if magnification(framed, view, viewport) < 1.0 {
return fit(region.0, region.1, viewport.0.max(1), viewport.1.max(1));
}
region
}
impl DevelopSession {