From fa42a26f6fa2f6e1132aec4977df2e1bccf9fc99 Mon Sep 17 00:00:00 2001 From: Tom Binford Date: Sat, 24 Jun 2023 05:28:02 -0700 Subject: Improve image rendering under rotation when exporting to PNG (#1547) --- src/export/render.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/export/render.rs b/src/export/render.rs index 3a5f0d0e..02c10e61 100644 --- a/src/export/render.rs +++ b/src/export/render.rs @@ -489,13 +489,19 @@ fn render_image( let view_height = size.y.to_f32(); let aspect = (image.width() as f32) / (image.height() as f32); - let scale = ts.sx.max(ts.sy); - let w = (scale * view_width.max(aspect * view_height)).ceil() as u32; + // For better-looking output, resize `image` to its final size before painting it to `canvas`. + // See https://github.com/typst/typst/issues/1404#issuecomment-1598374652 for the math. + let theta = f32::atan2(-ts.kx, ts.sx); + // To avoid division by 0, choose the one of { sin, cos } that is further from 0. + let prefer_sin = theta.sin().abs() > std::f32::consts::FRAC_1_SQRT_2; + let scale_x = + f32::abs(if prefer_sin { ts.kx / theta.sin() } else { ts.sx / theta.cos() }); + let w = (scale_x * view_width.max(aspect * view_height)).ceil() as u32; let h = ((w as f32) / aspect).ceil() as u32; let pixmap = scaled_texture(image, w, h)?; - let scale_x = view_width / pixmap.width() as f32; - let scale_y = view_height / pixmap.height() as f32; + let paint_scale_x = view_width / pixmap.width() as f32; + let paint_scale_y = view_height / pixmap.height() as f32; let paint = sk::Paint { shader: sk::Pattern::new( @@ -503,7 +509,7 @@ fn render_image( sk::SpreadMode::Pad, sk::FilterQuality::Nearest, 1.0, - sk::Transform::from_scale(scale_x, scale_y), + sk::Transform::from_scale(paint_scale_x, paint_scale_y), ), ..Default::default() }; -- cgit v1.2.3