[librsvg: 1/2] (#677) - Do not clip the rightmost/bottomost pixels of an image with partial pixel coverage




commit 5e454178f67695111b93f55b7beaf7e898665f63
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Jun 7 17:09:26 2021 -0500

    (#677) - Do not clip the rightmost/bottomost pixels of an image with partial pixel coverage
    
    In rsvg-convert, to compute the pixel size of PNG output, we now
    ceil(size) instead of round(size).  This prevents clipping of the last
    row or column.
    
    This is also in place now for the legacy functions that output to pixbufs.
    
    Fixes https://gitlab.gnome.org/GNOME/librsvg/-/issues/677
    
    Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/543>

 src/bin/rsvg-convert.rs                      | 5 +++--
 src/c_api/pixbuf_utils.rs                    | 4 ++--
 tests/fixtures/cmdline/677-partial-pixel.svg | 7 +++++++
 tests/src/cmdline/rsvg_convert.rs            | 8 ++++++++
 4 files changed, 20 insertions(+), 4 deletions(-)
---
diff --git a/src/bin/rsvg-convert.rs b/src/bin/rsvg-convert.rs
index 8d76a1c5..152b7873 100644
--- a/src/bin/rsvg-convert.rs
+++ b/src/bin/rsvg-convert.rs
@@ -204,8 +204,9 @@ impl Surface {
     }
 
     fn new_for_png(size: Size, stream: OutputStream) -> Result<Self, Error> {
-        let w = checked_i32(size.w.round())?;
-        let h = checked_i32(size.h.round())?;
+        // We use ceil() to avoid chopping off the last pixel if it is partially covered.
+        let w = checked_i32(size.w.ceil())?;
+        let h = checked_i32(size.h.ceil())?;
         let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, w, h)?;
         Ok(Self::Png(surface, stream))
     }
diff --git a/src/c_api/pixbuf_utils.rs b/src/c_api/pixbuf_utils.rs
index 017d0dcb..dbc99a0c 100644
--- a/src/c_api/pixbuf_utils.rs
+++ b/src/c_api/pixbuf_utils.rs
@@ -121,8 +121,8 @@ fn render_to_pixbuf_at_size(
 
     let surface = cairo::ImageSurface::create(
         cairo::Format::ARgb32,
-        checked_i32(desired_width.round())?,
-        checked_i32(desired_height.round())?,
+        checked_i32(desired_width.ceil())?,
+        checked_i32(desired_height.ceil())?,
     )?;
 
     {
diff --git a/tests/fixtures/cmdline/677-partial-pixel.svg b/tests/fixtures/cmdline/677-partial-pixel.svg
new file mode 100644
index 00000000..aeac8c30
--- /dev/null
+++ b/tests/fixtures/cmdline/677-partial-pixel.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"; width="1.2" height="1.8">
+  <!-- Output should be an image 2x2 pixels in size, with partial coverage for the pixels
+       on the right and bottom.
+   -->
+  <rect x="0" y="0" width="1.2" height="1.8" fill="lime"/>
+</svg>
diff --git a/tests/src/cmdline/rsvg_convert.rs b/tests/src/cmdline/rsvg_convert.rs
index 5dbdb65c..ab35709e 100644
--- a/tests/src/cmdline/rsvg_convert.rs
+++ b/tests/src/cmdline/rsvg_convert.rs
@@ -541,6 +541,14 @@ fn pdf_page_size() {
         .stdout(file::is_pdf().with_page_size(200, 100, 72.0));
 }
 
+#[test]
+fn does_not_clip_partial_coverage_pixels() {
+    RsvgConvert::new_with_input("tests/fixtures/cmdline/677-partial-pixel.svg")
+        .assert()
+        .success()
+        .stdout(file::is_png().with_size(2, 2));
+}
+
 #[test]
 fn background_color_option_with_valid_color() {
     RsvgConvert::accepts_arg("--background-color=LimeGreen");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]