From 1a7f7498cdbd87813b72f150c2544766bd36fb22 Mon Sep 17 00:00:00 2001 From: Julian Mutter Date: Thu, 23 Nov 2023 12:23:20 +0100 Subject: [PATCH] Implement pre-caching with lower resolution --- src/cache.rs | 42 +++++++++++++++++++++++++++--------------- src/draw.rs | 2 +- src/ui.rs | 19 ++++++++++++++++--- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/cache.rs b/src/cache.rs index 6c032cd..340366d 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -6,12 +6,12 @@ use log::{debug, error}; use poppler::Document; use std::{ cell::RefCell, - collections::BTreeMap, + collections::{BTreeMap, VecDeque}, rc::Rc, time::{Duration, Instant}, }; -type PageNumber = usize; +pub type PageNumber = usize; pub type MyPageType = Texture; pub struct PageCache { @@ -49,22 +49,29 @@ impl PageCache { } } - pub fn cache_page(&mut self, page_number: PageNumber, height: i32) -> bool { + pub fn cache_page(&mut self, page_number: PageNumber, height: i32) -> Option { debug!("Caching page {}", page_number); let begin_of_cashing = Instant::now(); if let Some(page) = self.pages.get(&page_number) { if page.height() >= height { debug!("Page already in cache"); - return false; + return None; } } + let mut response = None; + if let Some(page) = self.document.page(page_number as i32) { let pages = vec![Rc::new(page)]; let texture = draw::draw_pages_to_texture(&pages, height); + let page = Rc::new(texture); // Overwrite page with lower resolution if exists - self.pages.insert(page_number, Rc::new(texture)); + let previous_page = self.pages.insert(page_number, Rc::clone(&page)); + let page_resolution_upgraded = previous_page.is_some(); + if page_resolution_upgraded { + response = Some(CacheResponse::PageResolutionUpgraded { page_number, page }); + } if self.pages.len() > self.max_num_stored_pages && self.pages.len() > 2 { let _result = self.remove_most_distant_page(); @@ -75,7 +82,7 @@ impl PageCache { page_number, begin_of_cashing.elapsed().as_millis() ); - true + response } fn remove_most_distant_page(&mut self) -> anyhow::Result<()> { @@ -114,10 +121,7 @@ impl PageCache { fn process_command(&mut self, command: CacheCommand) -> Result> { debug!("Processing command: {:?}...", command); match command { - CacheCommand::Cache(command) => { - self.cache_page(command.page, command.height); - Ok(None) - } + CacheCommand::Cache(command) => Ok(self.cache_page(command.page, command.height)), CacheCommand::Retrieve(command) => match command { RetrievePagesCommand::GetCurrentTwoPages { page_left_number } => { let page_left = self.get_page_or_cache(page_left_number)?; @@ -162,11 +166,15 @@ pub enum CacheResponse { page_left: Rc, page_right: Rc, }, + PageResolutionUpgraded { + page_number: PageNumber, + page: Rc, + }, } pub struct SyncCacheCommandChannel { retrieve_commands: Vec, - cache_commands: Vec, + cache_commands: VecDeque, } pub struct SyncCacheCommandSender { @@ -181,7 +189,7 @@ impl SyncCacheCommandChannel { pub fn open() -> (SyncCacheCommandSender, SyncCacheCommandReceiver) { let channel = SyncCacheCommandChannel { retrieve_commands: Vec::new(), - cache_commands: Vec::new(), + cache_commands: VecDeque::new(), }; let channel = Rc::new(RefCell::new(channel)); @@ -205,11 +213,15 @@ impl SyncCacheCommandSender { pub fn send_cache_commands(&self, pages: &[PageNumber], height: i32) { for &page in pages { - // Make newest message the most important + // Make message in front the most important self.channel .borrow_mut() .cache_commands - .push(CachePageCommand { page, height }); + .push_front(CachePageCommand { page, height: 10 }); // Cache with lower resolution + self.channel + .borrow_mut() + .cache_commands + .push_back(CachePageCommand { page, height }); } } } @@ -223,7 +235,7 @@ impl SyncCacheCommandReceiver { let mut channel = self.channel.borrow_mut(); if let Some(command) = channel.retrieve_commands.pop() { return Some(CacheCommand::Retrieve(command)); - } else if let Some(command) = channel.cache_commands.pop() { + } else if let Some(command) = channel.cache_commands.pop_front() { return Some(CacheCommand::Cache(command)); } None diff --git a/src/draw.rs b/src/draw.rs index 846acae..79c75b0 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -7,7 +7,7 @@ use log::debug; use poppler::Page; pub fn draw_pages_to_texture(pages: &[Rc], area_height: i32) -> Texture { - let area_height = i32::max(400, area_height); + let area_height = i32::max(10, area_height); let total_width_normalized: f64 = pages .iter() .map(|page| page.size()) diff --git a/src/ui.rs b/src/ui.rs index 3ea160e..55967b3 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -10,7 +10,7 @@ use gtk::{ }; use log::debug; -use crate::cache::{self, SyncCacheCommandSender}; +use crate::cache::{self, PageNumber, SyncCacheCommandSender}; use glib::clone; use gtk::prelude::*; @@ -27,7 +27,7 @@ pub struct Ui { } pub struct DocumentCanvas { - current_page_number: usize, + pub current_page_number: usize, pub num_pages: Option, page_cache_sender: SyncCacheCommandSender, } @@ -89,6 +89,13 @@ impl DocumentCanvas { ) } } + + pub fn is_left_page(&self, page_number: PageNumber) -> bool { + page_number == self.current_page_number + } + pub fn is_right_page(&self, page_number: PageNumber) -> bool { + page_number == self.current_page_number + 1 + } } pub fn toggle_fullscreen(ui: &Ui) { @@ -299,8 +306,14 @@ pub fn load_document(file: impl AsRef, ui: Rc>) { ui.borrow_mut().image_right.set_visible(true); let area_height = ui.borrow().image_left.height(); ui.borrow().document_canvas.as_ref().unwrap().cache_surrounding_pages(area_height); - debug!("Image size: {}, {}", ui.borrow().image_left.width(), ui.borrow().image_left.height()); + }, + cache::CacheResponse::PageResolutionUpgraded { page_number, page } => { + if ui.borrow().document_canvas.as_ref().unwrap().is_left_page(page_number){ + ui.borrow_mut().image_left.set_paintable(Some(page.as_ref())); + } else if ui.borrow().document_canvas.as_ref().unwrap().is_right_page(page_number){ + ui.borrow_mut().image_right.set_paintable(Some(page.as_ref())); } + } }), );