mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
@@ -1357,7 +1357,7 @@ impl DocView {
|
||||
let avail_w = (self.viewport_w - 2.0 * SIDE).max(100.0);
|
||||
let per_row = if self.layout == PageLayout::TwoUp { 2.0 } else { 1.0 };
|
||||
match self.fit {
|
||||
Fit::Width => self.zoom = (avail_w - GAP * (per_row - 1.0)) / (max_w * PT * per_row),
|
||||
Fit::Width => self.zoom = (avail_w - GAP * (per_row - 1.0)) / (w * PT * per_row),
|
||||
Fit::Page => {
|
||||
let zw = (avail_w - GAP * (per_row - 1.0)) / (w * PT * per_row);
|
||||
let zh = (self.viewport_h - 2.0 * MARGIN) / (h * PT);
|
||||
@@ -1369,6 +1369,16 @@ impl DocView {
|
||||
self.zoom = self.zoom.clamp(0.08, 64.0);
|
||||
}
|
||||
|
||||
/// Width of the scroll content. Single-page view sizes it to the page it shows, so a
|
||||
/// wider page elsewhere in the document can't push the shown one off-centre.
|
||||
fn content_width(&self, info: &DocInfo, avail_w: f32) -> f32 {
|
||||
let single = (self.layout == PageLayout::Single).then(|| self.current.min(info.pages.len().saturating_sub(1)));
|
||||
let shown = info.pages.iter().enumerate().filter(|&(i, _)| single.is_none_or(|c| c == i));
|
||||
let max_w = shown.map(|(_, p)| self.display_size(p).0).fold(0.0, f32::max);
|
||||
let per_row = if self.layout == PageLayout::TwoUp { 2.0 } else { 1.0 };
|
||||
(max_w * self.zoom * PT * per_row + 2.0 * SIDE).max(avail_w)
|
||||
}
|
||||
|
||||
/// Page rects in content coordinates (origin at the scroll content's top-left).
|
||||
fn layout(&self, info: &DocInfo, content_w: f32) -> Vec<Rect> {
|
||||
let s = self.zoom * PT;
|
||||
@@ -1755,11 +1765,7 @@ pub fn document_area(app: &mut PdfCraftApp, index: usize, ui: &mut egui::Ui) {
|
||||
Vec2::ZERO
|
||||
};
|
||||
|
||||
let max_w = info.pages.iter().map(|p| view.display_size(p).0).fold(0.0, f32::max)
|
||||
* view.zoom
|
||||
* PT
|
||||
* if view.layout == PageLayout::TwoUp { 2.0 } else { 1.0 };
|
||||
let content_w = (max_w + 2.0 * SIDE).max(avail.width());
|
||||
let content_w = view.content_width(info, avail.width());
|
||||
let rects = view.layout(info, content_w);
|
||||
let middle_gesture = view.auto_scroll.blocks_input();
|
||||
// Single page: when the whole page fits, the wheel would do nothing, so it turns pages
|
||||
@@ -4079,6 +4085,31 @@ trailer << /Root 1 0 R >>
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fit_width_fits_the_shown_page_in_single_page_view_only() {
|
||||
let page =
|
||||
|width: f32, height: f32| pdfcraft_render::PageInfo { width, height, label: String::new(), crop: [0.0, 0.0, width, height], rotation: 0 };
|
||||
let info = DocInfo { pages: vec![page(300.0, 400.0), page(600.0, 400.0)], ..Default::default() };
|
||||
let mut v = DocView::new(DocId(1), &info, ViewDefaults::default());
|
||||
(v.fit, v.viewport_w, v.viewport_h) = (Fit::Width, 1000.0, 800.0);
|
||||
v.layout = PageLayout::Single;
|
||||
v.fit_zoom(&info);
|
||||
let narrow = v.zoom;
|
||||
// The shown page fills the width between the side gutters, not centred for the wide page.
|
||||
let shown = v.layout(&info, v.content_width(&info, 1000.0))[0];
|
||||
assert!((shown.left() - SIDE).abs() < 1e-2 && (shown.width() - 860.0).abs() < 1e-2, "{shown:?}");
|
||||
v.current = 1;
|
||||
v.fit_zoom(&info);
|
||||
assert!((narrow / v.zoom - 2.0).abs() < 1e-3, "the narrow page gets twice the zoom of the wide one");
|
||||
// Scrolling views keep one zoom for the whole document.
|
||||
v.layout = PageLayout::Continuous;
|
||||
v.fit_zoom(&info);
|
||||
let wide = v.zoom;
|
||||
v.current = 0;
|
||||
v.fit_zoom(&info);
|
||||
assert_eq!(v.zoom, wide, "continuous fit width holds still across page sizes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn layouts_match_their_commands_and_names() {
|
||||
for l in PageLayout::ORDER {
|
||||
|
||||
Reference in New Issue
Block a user