Managed to render to png, still only proof of concept

This commit is contained in:
Julian Mutter 2023-11-22 19:35:16 +01:00
parent 1db3c212ba
commit b98ca6c9f6
4 changed files with 97 additions and 34 deletions

View File

@ -5,7 +5,7 @@ edition = "2021"
[dependencies] [dependencies]
poppler-rs = "0.22" poppler-rs = "0.22"
cairo-rs = "0.18.3" cairo-rs = { version = "0.18.3", features = ["png"] }
glib-macros = "0.18.3" glib-macros = "0.18.3"
gio = "0.18.3" gio = "0.18.3"
glib = "0.18.3" glib = "0.18.3"

View File

@ -1,3 +1,5 @@
use cairo::ImageSurface;
use gtk::gdk::Texture;
use poppler::{Document, Page}; use poppler::{Document, Page};
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
@ -8,8 +10,10 @@ use std::{
use async_channel::Sender; use async_channel::Sender;
use crate::draw;
type PageNumber = usize; type PageNumber = usize;
pub type MyPageType = Page; pub type MyPageType = Texture;
pub struct PageCache { pub struct PageCache {
document: Document, document: Document,
@ -39,7 +43,10 @@ impl PageCache {
} }
if let Some(page) = self.document.page(page_number as i32) { 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 { if self.pages.len() > self.max_num_stored_pages && self.pages.len() > 2 {
let _result = self.remove_most_distant_page(page_number); let _result = self.remove_most_distant_page(page_number);
@ -76,7 +83,9 @@ impl PageCache {
} }
CacheCommand::GetCurrentTwoPages { page_left_number } => { CacheCommand::GetCurrentTwoPages { page_left_number } => {
if let Some(page_left) = self.get_page(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) { if let Some(page_right) = self.get_page(page_left_number + 1) {
println!("got right page");
Some(CacheResponse::TwoPagesRetrieved { Some(CacheResponse::TwoPagesRetrieved {
page_left, page_left,
page_right, page_right,
@ -85,6 +94,7 @@ impl PageCache {
Some(CacheResponse::SinglePageRetrieved { page: page_left }) Some(CacheResponse::SinglePageRetrieved { page: page_left })
} }
} else { } else {
println!("did not get any page");
// TODO: if page left was not empty, this could be because page turning was too quick. // 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 // 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 None
@ -140,6 +150,7 @@ where
// response_sender.send_blocking(response).unwrap(); // response_sender.send_blocking(response).unwrap();
println!("Command processed, activating receiver...."); println!("Command processed, activating receiver....");
receiver(response); receiver(response);
println!("receiver done");
} }
} }
}); });

View File

@ -1,10 +1,27 @@
use std::{rc::Rc, time::Instant}; 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 poppler::Page;
use crate::ui::DocumentCanvas; 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( pub fn draw(
document_canvas: &Option<DocumentCanvas>, document_canvas: &Option<DocumentCanvas>,
context: &Context, context: &Context,
@ -17,12 +34,15 @@ pub fn draw(
if document_canvas.num_pages.unwrap_or(0) > 1 { if document_canvas.num_pages.unwrap_or(0) > 1 {
let mut pages = Vec::new(); let mut pages = Vec::new();
if let Some(page_left) = &document_canvas.left_page { 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)); pages.push(Rc::clone(page_left));
} }
if let Some(page_right) = &document_canvas.right_page { if let Some(page_right) = &document_canvas.right_page {
pages.push(Rc::clone(page_right)); pages.push(Rc::clone(page_right));
} }
draw_pages(&pages, context, area_width, area_height); // draw_pages(&pages, context, area_width, area_height);
} }
println!( println!(

View File

@ -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 async_channel::Sender;
use gtk::{ 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, glib, Application, ApplicationWindow, Box, Button, DrawingArea, FileChooserAction,
FileChooserDialog, HeaderBar, Label, Orientation, ResponseType, FileChooserDialog, HeaderBar, Image, Label, Orientation, ResponseType,
}; };
use crate::{ use crate::{
cache::{self, CacheCommand, MyPageType}, cache::{self, CacheCommand, MyPageType},
draw, draw,
}; };
use glib::clone; use glib::{clone, Bytes};
use gtk::prelude::*; use gtk::prelude::*;
pub struct Ui { pub struct Ui {
@ -18,7 +21,8 @@ pub struct Ui {
bottom_bar: gtk::Box, bottom_bar: gtk::Box,
header_bar: gtk::HeaderBar, header_bar: gtk::HeaderBar,
page_indicator: gtk::Label, page_indicator: gtk::Label,
drawing_area: gtk::DrawingArea, pub drawing_area: gtk::DrawingArea,
pub image: Image,
pub document_canvas: Option<DocumentCanvas>, pub document_canvas: Option<DocumentCanvas>,
} }
@ -178,6 +182,12 @@ impl Ui {
bottom_bar: Box::builder().hexpand_set(true).build(), bottom_bar: Box::builder().hexpand_set(true).build(),
header_bar: HeaderBar::builder().build(), header_bar: HeaderBar::builder().build(),
page_indicator: Label::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() drawing_area: DrawingArea::builder()
.width_request(400) .width_request(400)
.height_request(300) .height_request(300)
@ -189,7 +199,8 @@ impl Ui {
let ui = Rc::new(RefCell::new(ui)); let ui = Rc::new(RefCell::new(ui));
ui.borrow().header_bar.pack_start(&open_file_button); 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); app_wrapper.append(&ui.borrow().bottom_bar);
ui.borrow().bottom_bar.append(&ui.borrow().page_indicator); ui.borrow().bottom_bar.append(&ui.borrow().page_indicator);
@ -205,14 +216,21 @@ impl Ui {
process_right_click(&mut ui.borrow_mut(), x, y); process_right_click(&mut ui.borrow_mut(), x, y);
})); }));
ui.borrow().drawing_area.add_controller(click_left); // ui.borrow().drawing_area.add_controller(click_left);
ui.borrow().drawing_area.add_controller(click_right); // 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( // ui.borrow().drawing_area.set_draw_func(
glib::clone!(@weak ui => move |_area, context, w, h| { // glib::clone!(@weak ui => move |_area, context, w, h| {
draw::draw(&ui.borrow().document_canvas, 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() ui.borrow()
.window .window
@ -255,23 +273,37 @@ pub fn load_document(file: impl AsRef<Path>, ui: Rc<RefCell<Ui>>) {
let sender = cache::spawn_async_cache( let sender = cache::spawn_async_cache(
file, file,
clone!(@weak ui => move |cache_response| match cache_response { clone!(@weak ui => move |cache_response| match cache_response {
cache::CacheResponse::DocumentLoaded { num_pages } => { cache::CacheResponse::DocumentLoaded { num_pages } => {
ui.borrow_mut().document_canvas.as_mut().unwrap().num_pages = Some(num_pages); ui.borrow_mut().document_canvas.as_mut().unwrap().num_pages = Some(num_pages);
update_page_status(&ui.borrow()) update_page_status(&ui.borrow())
} }
cache::CacheResponse::SinglePageRetrieved { page } => { cache::CacheResponse::SinglePageRetrieved { page } => {
ui.borrow_mut().document_canvas.as_mut().unwrap().left_page = Some(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_mut().document_canvas.as_mut().unwrap().right_page = None;
ui.borrow().drawing_area.queue_draw(); ui.borrow().drawing_area.queue_draw();
} }
cache::CacheResponse::TwoPagesRetrieved { cache::CacheResponse::TwoPagesRetrieved {
page_left, page_left,
page_right, page_right,
} => { } => {
ui.borrow_mut().document_canvas.as_mut().unwrap().left_page = Some(page_left); 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); ui.borrow_mut().document_canvas.as_mut().unwrap().right_page = Some(page_right);
ui.borrow().drawing_area.queue_draw(); // 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();
}
}), }),
); );