Skip to content

Commit 9de93b4

Browse files
committed
Support floating point viewbox in resvg binary
Avoid rounding sizes for images until creating the pixmap, and always use the ceil for that to avoid truncating images. This requires a corresponding change to tiny-skia to add scale_by/scale_to_width/scale_to_height functions to tiny_skia_path::Size to match the implementations in IntSize.
1 parent cf024df commit 9de93b4

File tree

1 file changed

+19
-20
lines changed

1 file changed

+19
-20
lines changed

crates/resvg/src/main.rs

+19-20
Original file line numberDiff line numberDiff line change
@@ -389,30 +389,29 @@ enum FitTo {
389389
/// Keep original size.
390390
Original,
391391
/// Scale to width.
392-
Width(u32),
392+
Width(f32),
393393
/// Scale to height.
394-
Height(u32),
394+
Height(f32),
395395
/// Scale to size.
396-
Size(u32, u32),
396+
Size(f32, f32),
397397
/// Zoom by factor.
398398
Zoom(f32),
399399
}
400400

401401
impl FitTo {
402-
fn fit_to_size(&self, size: tiny_skia::IntSize) -> Option<tiny_skia::IntSize> {
402+
fn fit_to_size(&self, size: tiny_skia::Size) -> Option<tiny_skia::Size> {
403403
match *self {
404404
FitTo::Original => Some(size),
405405
FitTo::Width(w) => size.scale_to_width(w),
406406
FitTo::Height(h) => size.scale_to_height(h),
407-
FitTo::Size(w, h) => tiny_skia::IntSize::from_wh(w, h).map(|s| size.scale_to(s)),
407+
FitTo::Size(w, h) => tiny_skia::Size::from_wh(w, h).map(|s| size.scale_to(s)),
408408
FitTo::Zoom(z) => size.scale_by(z),
409409
}
410410
}
411411

412-
fn fit_to_transform(&self, size: tiny_skia::IntSize) -> tiny_skia::Transform {
413-
let size1 = size.to_size();
414-
let size2 = match self.fit_to_size(size) {
415-
Some(v) => v.to_size(),
412+
fn fit_to_transform(&self, size1: tiny_skia::Size) -> tiny_skia::Transform {
413+
let size2 = match self.fit_to_size(size1) {
414+
Some(v) => v,
416415
None => return tiny_skia::Transform::default(),
417416
};
418417
tiny_skia::Transform::from_scale(
@@ -526,13 +525,13 @@ fn parse_args() -> Result<Args, String> {
526525
let mut default_size = usvg::Size::from_wh(100.0, 100.0).unwrap();
527526
if let (Some(w), Some(h)) = (args.width, args.height) {
528527
default_size = usvg::Size::from_wh(w as f32, h as f32).unwrap();
529-
fit_to = FitTo::Size(w, h);
528+
fit_to = FitTo::Size(w as f32, h as f32);
530529
} else if let Some(w) = args.width {
531530
default_size = usvg::Size::from_wh(w as f32, 100.0).unwrap();
532-
fit_to = FitTo::Width(w);
531+
fit_to = FitTo::Width(w as f32);
533532
} else if let Some(h) = args.height {
534533
default_size = usvg::Size::from_wh(100.0, h as f32).unwrap();
535-
fit_to = FitTo::Height(h);
534+
fit_to = FitTo::Height(h as f32);
536535
} else if let Some(z) = args.zoom {
537536
fit_to = FitTo::Zoom(z);
538537
}
@@ -681,19 +680,19 @@ fn render_svg(args: &Args, tree: &usvg::Tree) -> Result<tiny_skia::Pixmap, Strin
681680

682681
let size = args
683682
.fit_to
684-
.fit_to_size(bbox.size().to_int_size())
683+
.fit_to_size(bbox.size())
685684
.ok_or_else(|| "target size is zero".to_string())?;
686685

687686
// Unwrap is safe, because `size` is already valid.
688-
let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).unwrap();
687+
let mut pixmap = tiny_skia::Pixmap::new(size.width().ceil() as u32, size.height().ceil() as u32).unwrap();
689688

690689
if !args.export_area_page {
691690
if let Some(background) = args.background {
692691
pixmap.fill(svg_to_skia_color(background));
693692
}
694693
}
695694

696-
let ts = args.fit_to.fit_to_transform(tree.size().to_int_size());
695+
let ts = args.fit_to.fit_to_transform(tree.size());
697696

698697
resvg::render_node(node, ts, &mut pixmap.as_mut());
699698

@@ -702,11 +701,11 @@ fn render_svg(args: &Args, tree: &usvg::Tree) -> Result<tiny_skia::Pixmap, Strin
702701

703702
let size = args
704703
.fit_to
705-
.fit_to_size(tree.size().to_int_size())
704+
.fit_to_size(tree.size())
706705
.ok_or_else(|| "target size is zero".to_string())?;
707706

708707
// Unwrap is safe, because `size` is already valid.
709-
let mut page_pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).unwrap();
708+
let mut page_pixmap = tiny_skia::Pixmap::new(size.width().ceil() as u32, size.height().ceil() as u32).unwrap();
710709

711710
if let Some(background) = args.background {
712711
page_pixmap.fill(svg_to_skia_color(background));
@@ -727,17 +726,17 @@ fn render_svg(args: &Args, tree: &usvg::Tree) -> Result<tiny_skia::Pixmap, Strin
727726
} else {
728727
let size = args
729728
.fit_to
730-
.fit_to_size(tree.size().to_int_size())
729+
.fit_to_size(tree.size())
731730
.ok_or_else(|| "target size is zero".to_string())?;
732731

733732
// Unwrap is safe, because `size` is already valid.
734-
let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).unwrap();
733+
let mut pixmap = tiny_skia::Pixmap::new(size.width().ceil() as u32, size.height().ceil() as u32).unwrap();
735734

736735
if let Some(background) = args.background {
737736
pixmap.fill(svg_to_skia_color(background));
738737
}
739738

740-
let ts = args.fit_to.fit_to_transform(tree.size().to_int_size());
739+
let ts = args.fit_to.fit_to_transform(tree.size());
741740

742741
resvg::render(tree, ts, &mut pixmap.as_mut());
743742

0 commit comments

Comments
 (0)