From 587599f50be5b9ef3276f76c8d429fb626d25c2d Mon Sep 17 00:00:00 2001 From: Sophie Herold Date: Mon, 17 Apr 2023 22:38:52 +0200 Subject: [PATCH] print: Render SVG for correct size Closes #140 Part-of: --- src/decoder/formats/svg.rs | 20 +++++++++++++++++ src/decoder/mod.rs | 2 +- src/widgets/image.rs | 1 + src/widgets/print.rs | 44 ++++++++++++++++++++++++-------------- 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/decoder/formats/svg.rs b/src/decoder/formats/svg.rs index 2424efb..7f989e6 100644 --- a/src/decoder/formats/svg.rs +++ b/src/decoder/formats/svg.rs @@ -177,6 +177,26 @@ impl Svg { Ok(()) } + + pub fn render_print( + file: &gio::File, + width: i32, + height: i32, + ) -> anyhow::Result { + let handle = rsvg::Loader::new().read_file(file, gio::Cancellable::NONE)?; + let renderer = rsvg::CairoRenderer::new(&handle); + let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?; + let context = cairo::Context::new(&surface)?; + renderer + .render_document( + &context, + &cairo::Rectangle::new(0., 0., width as f64, height as f64), + ) + .context("Failed to render image")?; + drop(context); + + Ok(surface) + } } pub fn svg_dimensions(renderer: &rsvg::CairoRenderer) -> (u32, u32) { diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 8ac148d..37a7708 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -1,5 +1,5 @@ ///! Decodes several image formats -mod formats; +pub mod formats; pub mod tiling; pub use formats::ImageDimensionDetails; diff --git a/src/widgets/image.rs b/src/widgets/image.rs index 3592e9f..73b964f 100644 --- a/src/widgets/image.rs +++ b/src/widgets/image.rs @@ -1014,6 +1014,7 @@ impl LpImage { &snapshot, -orientation.rotation as f32, orientation.mirrored, + scale, ); self.imp() diff --git a/src/widgets/print.rs b/src/widgets/print.rs index 1c56b72..7bd8a61 100644 --- a/src/widgets/print.rs +++ b/src/widgets/print.rs @@ -1,5 +1,6 @@ //! The print layout widget that also coordinates the print process +use crate::decoder; use crate::deps::*; use crate::widgets::{LpImage, LpPrintPreview}; @@ -395,30 +396,41 @@ impl LpPrint { let cairo_dpi = print_context.dpi_x(); - let (orig_width, _) = image.image_size(); + let (orig_width, orig_height) = image.image_size(); let texture_scale = self.user_width() / orig_width as f64; let cairo_scale = cairo_dpi / self.dpi(); - let texture = image.print_data(texture_scale).unwrap(); + let cairo_surface = if let Some(decoder::ImageFormat::Svg) = image.format() { + // Render SVG to exact needed sizes + // TODO: This should be async + decoder::formats::Svg::render_print( + &image.file().unwrap(), + (orig_width as f64 * texture_scale) as i32, + (orig_height as f64 * texture_scale) as i32, + ) + .unwrap() + } else { + let texture = image.print_data(texture_scale).unwrap(); - let mut downloader = gdk::TextureDownloader::new(&texture); - downloader.set_format(gdk::MemoryFormat::B8g8r8a8Premultiplied); + let mut downloader = gdk::TextureDownloader::new(&texture); + downloader.set_format(gdk::MemoryFormat::B8g8r8a8Premultiplied); - let (data, stride) = downloader.download_bytes(); - let data = data.to_vec(); + let (data, stride) = downloader.download_bytes(); + let data = data.to_vec(); - let width = texture.width(); - let height = texture.height(); + let width = texture.width(); + let height = texture.height(); - let cairo_surface = cairo::ImageSurface::create_for_data( - data, - cairo::Format::ARgb32, - width, - height, - stride as i32, - ) - .unwrap(); + cairo::ImageSurface::create_for_data( + data, + cairo::Format::ARgb32, + width, + height, + stride as i32, + ) + .unwrap() + }; let cairo_context = print_context.cairo_context(); cairo_context.scale(cairo_scale, cairo_scale);