Implement pre-caching with lower resolution

This commit is contained in:
Julian Mutter 2023-11-23 12:23:20 +01:00
parent 75e1da0097
commit 1a7f7498cd
3 changed files with 44 additions and 19 deletions

View File

@ -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<CacheResponse> {
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<Option<CacheResponse>> {
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<MyPageType>,
page_right: Rc<MyPageType>,
},
PageResolutionUpgraded {
page_number: PageNumber,
page: Rc<MyPageType>,
},
}
pub struct SyncCacheCommandChannel {
retrieve_commands: Vec<RetrievePagesCommand>,
cache_commands: Vec<CachePageCommand>,
cache_commands: VecDeque<CachePageCommand>,
}
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

View File

@ -7,7 +7,7 @@ use log::debug;
use poppler::Page;
pub fn draw_pages_to_texture(pages: &[Rc<Page>], 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())

View File

@ -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<usize>,
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<Path>, ui: Rc<RefCell<Ui>>) {
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()));
}
}
}),
);