print: Render SVG for correct size

Closes #140

Part-of: <https://gitlab.gnome.org/Incubator/loupe/-/merge_requests/165>
This commit is contained in:
Sophie Herold 2023-04-17 22:38:52 +02:00 • committed by Marge Bot
parent ae5ca76176
commit 587599f50b
4 changed files with 50 additions and 17 deletions

View file

@ -177,6 +177,26 @@ impl Svg {
Ok(()) Ok(())
} }
pub fn render_print(
file: &gio::File,
width: i32,
height: i32,
) -> anyhow::Result<cairo::ImageSurface> {
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) { pub fn svg_dimensions(renderer: &rsvg::CairoRenderer) -> (u32, u32) {

View file

@ -1,5 +1,5 @@
///! Decodes several image formats ///! Decodes several image formats
mod formats; pub mod formats;
pub mod tiling; pub mod tiling;
pub use formats::ImageDimensionDetails; pub use formats::ImageDimensionDetails;

View file

@ -1014,6 +1014,7 @@ impl LpImage {
&snapshot, &snapshot,
-orientation.rotation as f32, -orientation.rotation as f32,
orientation.mirrored, orientation.mirrored,
scale,
); );
self.imp() self.imp()

View file

@ -1,5 +1,6 @@
//! The print layout widget that also coordinates the print process //! The print layout widget that also coordinates the print process
use crate::decoder;
use crate::deps::*; use crate::deps::*;
use crate::widgets::{LpImage, LpPrintPreview}; use crate::widgets::{LpImage, LpPrintPreview};
@ -395,30 +396,41 @@ impl LpPrint {
let cairo_dpi = print_context.dpi_x(); 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 texture_scale = self.user_width() / orig_width as f64;
let cairo_scale = cairo_dpi / self.dpi(); 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); let mut downloader = gdk::TextureDownloader::new(&texture);
downloader.set_format(gdk::MemoryFormat::B8g8r8a8Premultiplied); downloader.set_format(gdk::MemoryFormat::B8g8r8a8Premultiplied);
let (data, stride) = downloader.download_bytes(); let (data, stride) = downloader.download_bytes();
let data = data.to_vec(); let data = data.to_vec();
let width = texture.width(); let width = texture.width();
let height = texture.height(); let height = texture.height();
let cairo_surface = cairo::ImageSurface::create_for_data( cairo::ImageSurface::create_for_data(
data, data,
cairo::Format::ARgb32, cairo::Format::ARgb32,
width, width,
height, height,
stride as i32, stride as i32,
) )
.unwrap(); .unwrap()
};
let cairo_context = print_context.cairo_context(); let cairo_context = print_context.cairo_context();
cairo_context.scale(cairo_scale, cairo_scale); cairo_context.scale(cairo_scale, cairo_scale);