Implement pre-caching with lower resolution
This commit is contained in:
parent
75e1da0097
commit
1a7f7498cd
42
src/cache.rs
42
src/cache.rs
@ -6,12 +6,12 @@ use log::{debug, error};
|
|||||||
use poppler::Document;
|
use poppler::Document;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::BTreeMap,
|
collections::{BTreeMap, VecDeque},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
type PageNumber = usize;
|
pub type PageNumber = usize;
|
||||||
pub type MyPageType = Texture;
|
pub type MyPageType = Texture;
|
||||||
|
|
||||||
pub struct PageCache {
|
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);
|
debug!("Caching page {}", page_number);
|
||||||
let begin_of_cashing = Instant::now();
|
let begin_of_cashing = Instant::now();
|
||||||
if let Some(page) = self.pages.get(&page_number) {
|
if let Some(page) = self.pages.get(&page_number) {
|
||||||
if page.height() >= height {
|
if page.height() >= height {
|
||||||
debug!("Page already in cache");
|
debug!("Page already in cache");
|
||||||
return false;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut response = None;
|
||||||
|
|
||||||
if let Some(page) = self.document.page(page_number as i32) {
|
if let Some(page) = self.document.page(page_number as i32) {
|
||||||
let pages = vec![Rc::new(page)];
|
let pages = vec![Rc::new(page)];
|
||||||
let texture = draw::draw_pages_to_texture(&pages, height);
|
let texture = draw::draw_pages_to_texture(&pages, height);
|
||||||
|
let page = Rc::new(texture);
|
||||||
|
|
||||||
// Overwrite page with lower resolution if exists
|
// 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 {
|
if self.pages.len() > self.max_num_stored_pages && self.pages.len() > 2 {
|
||||||
let _result = self.remove_most_distant_page();
|
let _result = self.remove_most_distant_page();
|
||||||
@ -75,7 +82,7 @@ impl PageCache {
|
|||||||
page_number,
|
page_number,
|
||||||
begin_of_cashing.elapsed().as_millis()
|
begin_of_cashing.elapsed().as_millis()
|
||||||
);
|
);
|
||||||
true
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_most_distant_page(&mut self) -> anyhow::Result<()> {
|
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>> {
|
fn process_command(&mut self, command: CacheCommand) -> Result<Option<CacheResponse>> {
|
||||||
debug!("Processing command: {:?}...", command);
|
debug!("Processing command: {:?}...", command);
|
||||||
match command {
|
match command {
|
||||||
CacheCommand::Cache(command) => {
|
CacheCommand::Cache(command) => Ok(self.cache_page(command.page, command.height)),
|
||||||
self.cache_page(command.page, command.height);
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
CacheCommand::Retrieve(command) => match command {
|
CacheCommand::Retrieve(command) => match command {
|
||||||
RetrievePagesCommand::GetCurrentTwoPages { page_left_number } => {
|
RetrievePagesCommand::GetCurrentTwoPages { page_left_number } => {
|
||||||
let page_left = self.get_page_or_cache(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_left: Rc<MyPageType>,
|
||||||
page_right: Rc<MyPageType>,
|
page_right: Rc<MyPageType>,
|
||||||
},
|
},
|
||||||
|
PageResolutionUpgraded {
|
||||||
|
page_number: PageNumber,
|
||||||
|
page: Rc<MyPageType>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SyncCacheCommandChannel {
|
pub struct SyncCacheCommandChannel {
|
||||||
retrieve_commands: Vec<RetrievePagesCommand>,
|
retrieve_commands: Vec<RetrievePagesCommand>,
|
||||||
cache_commands: Vec<CachePageCommand>,
|
cache_commands: VecDeque<CachePageCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SyncCacheCommandSender {
|
pub struct SyncCacheCommandSender {
|
||||||
@ -181,7 +189,7 @@ impl SyncCacheCommandChannel {
|
|||||||
pub fn open() -> (SyncCacheCommandSender, SyncCacheCommandReceiver) {
|
pub fn open() -> (SyncCacheCommandSender, SyncCacheCommandReceiver) {
|
||||||
let channel = SyncCacheCommandChannel {
|
let channel = SyncCacheCommandChannel {
|
||||||
retrieve_commands: Vec::new(),
|
retrieve_commands: Vec::new(),
|
||||||
cache_commands: Vec::new(),
|
cache_commands: VecDeque::new(),
|
||||||
};
|
};
|
||||||
let channel = Rc::new(RefCell::new(channel));
|
let channel = Rc::new(RefCell::new(channel));
|
||||||
|
|
||||||
@ -205,11 +213,15 @@ impl SyncCacheCommandSender {
|
|||||||
|
|
||||||
pub fn send_cache_commands(&self, pages: &[PageNumber], height: i32) {
|
pub fn send_cache_commands(&self, pages: &[PageNumber], height: i32) {
|
||||||
for &page in pages {
|
for &page in pages {
|
||||||
// Make newest message the most important
|
// Make message in front the most important
|
||||||
self.channel
|
self.channel
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.cache_commands
|
.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();
|
let mut channel = self.channel.borrow_mut();
|
||||||
if let Some(command) = channel.retrieve_commands.pop() {
|
if let Some(command) = channel.retrieve_commands.pop() {
|
||||||
return Some(CacheCommand::Retrieve(command));
|
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));
|
return Some(CacheCommand::Cache(command));
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
@ -7,7 +7,7 @@ use log::debug;
|
|||||||
use poppler::Page;
|
use poppler::Page;
|
||||||
|
|
||||||
pub fn draw_pages_to_texture(pages: &[Rc<Page>], area_height: i32) -> Texture {
|
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
|
let total_width_normalized: f64 = pages
|
||||||
.iter()
|
.iter()
|
||||||
.map(|page| page.size())
|
.map(|page| page.size())
|
||||||
|
19
src/ui.rs
19
src/ui.rs
@ -10,7 +10,7 @@ use gtk::{
|
|||||||
};
|
};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::cache::{self, SyncCacheCommandSender};
|
use crate::cache::{self, PageNumber, SyncCacheCommandSender};
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ pub struct Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct DocumentCanvas {
|
pub struct DocumentCanvas {
|
||||||
current_page_number: usize,
|
pub current_page_number: usize,
|
||||||
pub num_pages: Option<usize>,
|
pub num_pages: Option<usize>,
|
||||||
page_cache_sender: SyncCacheCommandSender,
|
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) {
|
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);
|
ui.borrow_mut().image_right.set_visible(true);
|
||||||
let area_height = ui.borrow().image_left.height();
|
let area_height = ui.borrow().image_left.height();
|
||||||
ui.borrow().document_canvas.as_ref().unwrap().cache_surrounding_pages(area_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()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user