From c3928880fb86d8e4fc41416fec0e14db1391a022 Mon Sep 17 00:00:00 2001 From: Julian Mutter Date: Tue, 10 Oct 2023 10:07:54 +0200 Subject: [PATCH] Implement two page drawing --- src/ui.rs | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 7 deletions(-) diff --git a/src/ui.rs b/src/ui.rs index 64f63a8..0c2fb13 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -47,7 +47,18 @@ pub fn toggle_fullscreen(ui: &Ui) { fn update_page_status(ui: &Ui) { let page_status = match &ui.document_canvas { - Some(doc) => format!("{} / {}", doc.current_page_number, doc.num_pages), + Some(doc) => { + if doc.num_pages == 1 { + format!("{} / {}", doc.current_page_number, doc.num_pages) + } else { + format!( + "{}-{} / {}", + doc.current_page_number, + doc.current_page_number + 1, + doc.num_pages + ) + } + } None => "No document loaded!".to_string(), }; ui.page_indicator.set_label(page_status.as_str()); @@ -63,7 +74,8 @@ fn process_touch(ui: &mut Ui, x: f64, y: f64) { let center = ui.drawing_area.width() / 2; if y < (ui.drawing_area.height() / 5) as f64 { toggle_fullscreen(ui); - } else if x > center as f64 && doc.current_page_number < doc.num_pages { + } else if x > center as f64 && doc.current_page_number < doc.num_pages - 1 { + // Do not load last page since showing two pages would result in error doc.current_page_number += 1; } else if x < center as f64 && doc.current_page_number > 1 { doc.current_page_number -= 1; @@ -87,7 +99,12 @@ impl Ui { bottom_bar: Box::builder().hexpand_set(true).build(), header_bar: HeaderBar::builder().build(), page_indicator: Label::builder().build(), - drawing_area: DrawingArea::builder().hexpand(true).vexpand(true).build(), + drawing_area: DrawingArea::builder() + .width_request(400) + .height_request(300) + .hexpand(true) + .vexpand(true) + .build(), drawing_context: create_drawing_context(), document_canvas: None, }; @@ -138,11 +155,93 @@ fn draw(ui: &Ui, area: &DrawingArea, context: &Context) { return; } let document_canvas = ui.document_canvas.as_ref().unwrap(); + if document_canvas.num_pages > 1 { + draw_two_pages(ui, area, context); + } else { + draw_single_page(ui, area, context); + } +} + +fn draw_two_pages(ui: &Ui, area: &DrawingArea, context: &Context) { + if ui.document_canvas.is_none() { + return; + } + let document_canvas = ui.document_canvas.as_ref().unwrap(); + + // Add white background + // context.set_source_rgba(1.0, 1.0, 1.0, 1.0); + // context.fill().unwrap(); + // context.paint().unwrap(); + + let page_left = document_canvas + .document + .page(document_canvas.current_page_number - 1) + .unwrap(); + let page_right = document_canvas + .document + .page(document_canvas.current_page_number) + .unwrap(); + + let (w_left, h_left) = page_left.size(); + let (w_right, h_right) = page_right.size(); + + let h_max = f64::max(h_left, h_right); + // Make sure both pages are rendered with the same height + let w_max = match h_left < h_right { + true => w_left * h_right / h_left + w_right, + false => w_left + w_right * h_left / h_right, + }; + + let h_scale = area.height() as f64 / h_max; + let w_scale = area.width() as f64 / w_max; + let scale = f64::min(h_scale, w_scale); + let h_page = h_max * scale; + + let scale_left = h_page / h_left; + let scale_right = h_page / h_right; context.set_source_rgba(1.0, 1.0, 1.0, 1.0); - context.paint().unwrap(); - context.fill().expect("uh oh"); - context.paint().unwrap(); + context.save().unwrap(); + context.translate( + area.width() as f64 / 2.0 - w_left * scale_left, + area.height() as f64 / 2.0 - h_page / 2.0, + ); + // Poppler sometimes crops white border, draw it manually + context.rectangle(0.0, 0.0, w_left * scale_left, h_page); + context.fill().unwrap(); + context.scale(scale_left, scale_left); + page_left.render(context); + + context.restore().unwrap(); + context.translate( + area.width() as f64 / 2.0, + area.height() as f64 / 2.0 - h_page / 2.0, + ); + // Poppler sometimes crops white border, draw it manually + context.rectangle(0.0, 0.0, w_right * scale_right, h_page); + context.fill().unwrap(); + context.scale(scale_right, scale_right); + page_right.render(context); + + let r = ui.drawing_context.paint(); + match r { + Err(v) => println!("Error painting PDF: {v:?}"), + Ok(_v) => {} + } + + ui.drawing_context.show_page().unwrap(); +} +fn draw_single_page(ui: &Ui, area: &DrawingArea, context: &Context) { + if ui.document_canvas.is_none() { + return; + } + let document_canvas = ui.document_canvas.as_ref().unwrap(); + + // Draw background + // context.set_source_rgba(1.0, 1.0, 1.0, 1.0); + // context.paint().unwrap(); + // context.fill().expect("uh oh"); + // context.paint().unwrap(); let page = document_canvas .document @@ -152,7 +251,6 @@ fn draw(ui: &Ui, area: &DrawingArea, context: &Context) { let width_diff = area.width() as f64 / w; let height_diff = area.height() as f64 / h; - context.save().unwrap(); if width_diff > height_diff { context.translate( (area.width() as f64 - w * height_diff) / 2.0, @@ -167,6 +265,11 @@ fn draw(ui: &Ui, area: &DrawingArea, context: &Context) { context.scale(width_diff, width_diff); } + // Poppler sometimes crops white border, draw it manually + context.set_source_rgba(1.0, 1.0, 1.0, 1.0); + context.rectangle(0.0, 0.0, w, h); + context.fill().unwrap(); + page.render(context); let r = ui.drawing_context.paint();