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]
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"

View File

@ -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");
}
}
});

View File

@ -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!(

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 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();
}
}),
);