Managed to render to png, still only proof of concept
This commit is contained in:
parent
1db3c212ba
commit
b98ca6c9f6
@ -5,7 +5,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
poppler-rs = "0.22"
|
||||
cairo-rs = "0.18.3"
|
||||
cairo-rs = { version = "0.18.3", features = ["png"] }
|
||||
glib-macros = "0.18.3"
|
||||
gio = "0.18.3"
|
||||
glib = "0.18.3"
|
||||
|
15
src/cache.rs
15
src/cache.rs
@ -1,3 +1,5 @@
|
||||
use cairo::ImageSurface;
|
||||
use gtk::gdk::Texture;
|
||||
use poppler::{Document, Page};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
@ -8,8 +10,10 @@ use std::{
|
||||
|
||||
use async_channel::Sender;
|
||||
|
||||
use crate::draw;
|
||||
|
||||
type PageNumber = usize;
|
||||
pub type MyPageType = Page;
|
||||
pub type MyPageType = Texture;
|
||||
|
||||
pub struct PageCache {
|
||||
document: Document,
|
||||
@ -39,7 +43,10 @@ impl PageCache {
|
||||
}
|
||||
|
||||
if let Some(page) = self.document.page(page_number as i32) {
|
||||
self.pages.insert(page_number, Rc::new(page));
|
||||
let pages = vec![Rc::new(page)];
|
||||
let texture = draw::draw_pages_to_texture(&pages, 500, 500);
|
||||
|
||||
self.pages.insert(page_number, Rc::new(texture));
|
||||
|
||||
if self.pages.len() > self.max_num_stored_pages && self.pages.len() > 2 {
|
||||
let _result = self.remove_most_distant_page(page_number);
|
||||
@ -76,7 +83,9 @@ impl PageCache {
|
||||
}
|
||||
CacheCommand::GetCurrentTwoPages { page_left_number } => {
|
||||
if let Some(page_left) = self.get_page(page_left_number) {
|
||||
println!("got left page");
|
||||
if let Some(page_right) = self.get_page(page_left_number + 1) {
|
||||
println!("got right page");
|
||||
Some(CacheResponse::TwoPagesRetrieved {
|
||||
page_left,
|
||||
page_right,
|
||||
@ -85,6 +94,7 @@ impl PageCache {
|
||||
Some(CacheResponse::SinglePageRetrieved { page: page_left })
|
||||
}
|
||||
} else {
|
||||
println!("did not get any page");
|
||||
// TODO: if page left was not empty, this could be because page turning was too quick.
|
||||
// In this case, just not rendering the current page is okay, but when no more render requests are available, one would want to wait for the caching
|
||||
None
|
||||
@ -140,6 +150,7 @@ where
|
||||
// response_sender.send_blocking(response).unwrap();
|
||||
println!("Command processed, activating receiver....");
|
||||
receiver(response);
|
||||
println!("receiver done");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
24
src/draw.rs
24
src/draw.rs
@ -1,10 +1,27 @@
|
||||
use std::{rc::Rc, time::Instant};
|
||||
|
||||
use cairo::Context;
|
||||
use cairo::{Context, ImageSurface};
|
||||
use glib::Bytes;
|
||||
use gtk::{
|
||||
ffi::GtkImage,
|
||||
gdk::{ffi::gdk_pixbuf_get_from_surface, Texture},
|
||||
gdk_pixbuf::Pixbuf,
|
||||
};
|
||||
use poppler::Page;
|
||||
|
||||
use crate::ui::DocumentCanvas;
|
||||
|
||||
pub fn draw_pages_to_texture(pages: &[Rc<Page>], area_width: i32, area_height: i32) -> Texture {
|
||||
let surface =
|
||||
ImageSurface::create(cairo::Format::Rgb24, area_width as i32, area_height as i32).unwrap();
|
||||
let context = Context::new(&surface).unwrap();
|
||||
draw_pages(pages, &context, area_width, area_height);
|
||||
|
||||
let mut stream: Vec<u8> = Vec::new();
|
||||
surface.write_to_png(&mut stream).unwrap();
|
||||
Texture::from_bytes(&Bytes::from(&stream)).unwrap()
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
document_canvas: &Option<DocumentCanvas>,
|
||||
context: &Context,
|
||||
@ -17,12 +34,15 @@ pub fn draw(
|
||||
if document_canvas.num_pages.unwrap_or(0) > 1 {
|
||||
let mut pages = Vec::new();
|
||||
if let Some(page_left) = &document_canvas.left_page {
|
||||
// context
|
||||
// .set_source_surface(page_left.as_ref(), 0.0, 0.0)
|
||||
// .unwrap();
|
||||
pages.push(Rc::clone(page_left));
|
||||
}
|
||||
if let Some(page_right) = &document_canvas.right_page {
|
||||
pages.push(Rc::clone(page_right));
|
||||
}
|
||||
draw_pages(&pages, context, area_width, area_height);
|
||||
// draw_pages(&pages, context, area_width, area_height);
|
||||
}
|
||||
|
||||
println!(
|
||||
|
90
src/ui.rs
90
src/ui.rs
@ -1,16 +1,19 @@
|
||||
use std::{cell::RefCell, path::Path, rc::Rc};
|
||||
use std::{cell::RefCell, path::Path, rc::Rc, time::Instant};
|
||||
|
||||
use async_channel::Sender;
|
||||
use gtk::{
|
||||
ffi::{GtkImage, GtkPicture},
|
||||
gdk::{ffi::gdk_pixbuf_get_from_surface, Texture},
|
||||
gdk_pixbuf::{ffi::GdkPixbuf, Pixbuf},
|
||||
glib, Application, ApplicationWindow, Box, Button, DrawingArea, FileChooserAction,
|
||||
FileChooserDialog, HeaderBar, Label, Orientation, ResponseType,
|
||||
FileChooserDialog, HeaderBar, Image, Label, Orientation, ResponseType,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
cache::{self, CacheCommand, MyPageType},
|
||||
draw,
|
||||
};
|
||||
use glib::clone;
|
||||
use glib::{clone, Bytes};
|
||||
use gtk::prelude::*;
|
||||
|
||||
pub struct Ui {
|
||||
@ -18,7 +21,8 @@ pub struct Ui {
|
||||
bottom_bar: gtk::Box,
|
||||
header_bar: gtk::HeaderBar,
|
||||
page_indicator: gtk::Label,
|
||||
drawing_area: gtk::DrawingArea,
|
||||
pub drawing_area: gtk::DrawingArea,
|
||||
pub image: Image,
|
||||
pub document_canvas: Option<DocumentCanvas>,
|
||||
}
|
||||
|
||||
@ -178,6 +182,12 @@ impl Ui {
|
||||
bottom_bar: Box::builder().hexpand_set(true).build(),
|
||||
header_bar: HeaderBar::builder().build(),
|
||||
page_indicator: Label::builder().build(),
|
||||
image: Image::builder()
|
||||
.width_request(400)
|
||||
.height_request(300)
|
||||
.hexpand(true)
|
||||
.vexpand(true)
|
||||
.build(),
|
||||
drawing_area: DrawingArea::builder()
|
||||
.width_request(400)
|
||||
.height_request(300)
|
||||
@ -189,7 +199,8 @@ impl Ui {
|
||||
let ui = Rc::new(RefCell::new(ui));
|
||||
|
||||
ui.borrow().header_bar.pack_start(&open_file_button);
|
||||
app_wrapper.prepend(&ui.borrow().drawing_area);
|
||||
// app_wrapper.prepend(&ui.borrow().drawing_area);
|
||||
app_wrapper.prepend(&ui.borrow().image);
|
||||
app_wrapper.append(&ui.borrow().bottom_bar);
|
||||
ui.borrow().bottom_bar.append(&ui.borrow().page_indicator);
|
||||
|
||||
@ -205,14 +216,21 @@ impl Ui {
|
||||
process_right_click(&mut ui.borrow_mut(), x, y);
|
||||
}));
|
||||
|
||||
ui.borrow().drawing_area.add_controller(click_left);
|
||||
ui.borrow().drawing_area.add_controller(click_right);
|
||||
// ui.borrow().drawing_area.add_controller(click_left);
|
||||
// ui.borrow().drawing_area.add_controller(click_right);
|
||||
ui.borrow().image.add_controller(click_left);
|
||||
ui.borrow().image.add_controller(click_right);
|
||||
|
||||
ui.borrow().drawing_area.set_draw_func(
|
||||
glib::clone!(@weak ui => move |_area, context, w, h| {
|
||||
draw::draw(&ui.borrow().document_canvas, context, w, h);
|
||||
}),
|
||||
);
|
||||
// ui.borrow().drawing_area.set_draw_func(
|
||||
// glib::clone!(@weak ui => move |_area, context, w, h| {
|
||||
// draw::draw(&ui.borrow().document_canvas, context, w, h);
|
||||
// }),
|
||||
// );
|
||||
// ui.borrow().image.connect_paintable_notify(
|
||||
// glib::clone!(@weak ui => @default-panic, move |_| {
|
||||
// ui.borrow().document_canvas.as_ref().unwrap().cache_surrounding_pages();
|
||||
// }),
|
||||
// );
|
||||
|
||||
ui.borrow()
|
||||
.window
|
||||
@ -255,23 +273,37 @@ pub fn load_document(file: impl AsRef<Path>, ui: Rc<RefCell<Ui>>) {
|
||||
let sender = cache::spawn_async_cache(
|
||||
file,
|
||||
clone!(@weak ui => move |cache_response| match cache_response {
|
||||
cache::CacheResponse::DocumentLoaded { num_pages } => {
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().num_pages = Some(num_pages);
|
||||
update_page_status(&ui.borrow())
|
||||
}
|
||||
cache::CacheResponse::SinglePageRetrieved { page } => {
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().left_page = Some(page);
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().right_page = None;
|
||||
ui.borrow().drawing_area.queue_draw();
|
||||
}
|
||||
cache::CacheResponse::TwoPagesRetrieved {
|
||||
page_left,
|
||||
page_right,
|
||||
} => {
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().left_page = Some(page_left);
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().right_page = Some(page_right);
|
||||
ui.borrow().drawing_area.queue_draw();
|
||||
}
|
||||
cache::CacheResponse::DocumentLoaded { num_pages } => {
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().num_pages = Some(num_pages);
|
||||
update_page_status(&ui.borrow())
|
||||
}
|
||||
cache::CacheResponse::SinglePageRetrieved { page } => {
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().left_page = Some(page);
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().right_page = None;
|
||||
ui.borrow().drawing_area.queue_draw();
|
||||
}
|
||||
cache::CacheResponse::TwoPagesRetrieved {
|
||||
page_left,
|
||||
page_right,
|
||||
} => {
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().left_page = Some(Rc::clone(&page_left));
|
||||
ui.borrow_mut().document_canvas.as_mut().unwrap().right_page = Some(page_right);
|
||||
// unsafe{
|
||||
// let x = Pixbuf::new();
|
||||
// gdk_pixbuf_get_from_surface(page_left, 0, 0, page_left.width(), page_left.height());
|
||||
// }
|
||||
// ui.borrow_mut().image.bitstre
|
||||
// ui.borrow().drawing_area.queue_draw();
|
||||
println!("New Draw");
|
||||
let begin_of_drawing = Instant::now();
|
||||
ui.borrow_mut().image.set_from_paintable(Some(page_left.as_ref()));
|
||||
ui.borrow().image.queue_draw();
|
||||
println!(
|
||||
"Finished new drawing in {}ms",
|
||||
begin_of_drawing.elapsed().as_millis()
|
||||
);
|
||||
ui.borrow().document_canvas.as_ref().unwrap().cache_surrounding_pages();
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user