ropensci / rsvg

SVG renderer for R based on librsvg2
Other
97 stars 1 forks source link

Scaling / cropping regression in 2.4.0 rsvg_pdf output #36

Open robchallen opened 1 year ago

robchallen commented 1 year ago

Hi, thanks for creating rsvg

The cropping on scaling issue seen with bitmap outputs in #35 seems to persist in PDF output in version 2.4.0. I hope this is enough to demonstrate, (and that this is not an issue with my setup):

library(rsvg)
svg_text <- '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   width="100pt"
   height="100pt"
   viewBox="0 0 100 100"
   version="1.1"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">
   <g>
    <rect
       style="fill:#b3b3b3;stroke:#000000;"
       width="90"
       height="90"
       x="5"
       y="5" />
    <rect
       style="fill:#b3b3b3;stroke:#000000;"
       width="20"
       height="20"
       x="60"
       y="60" />
  </g>
</svg>
'

# EXPECTED: 
# a simple box centred in the pdf with a smaller box in the bottom right
# this renders fine as PDF without rescaling:
expected = tempfile(fileext = ".expected.pdf")
rsvg::rsvg_pdf(charToRaw(svg_text),file = expected)
rstudioapi::viewer(expected)

# NOT WORKING: 
# I expect the same image to be scaled to 50x50
# instead I see only the top left corner at the original scale
observed = tempfile(fileext = ".observed.pdf")
rsvg::rsvg_pdf(charToRaw(svg_text),file = observed,width = 50,height = 50)
rstudioapi::viewer(observed)

# NOT WORKING: 
# rsvg to svg also produces image that is not scaled but only shows the top left
# corner.
observed2 = tempfile(fileext = ".observed.svg")
rsvg::rsvg_svg(charToRaw(svg_text),file = observed2,width = 50,height = 50)
rstudioapi::viewer(observed2)
# N.B.Inspecting the new SVG there is only one path element - the smaller box is no
# longer there, it gets cropped out altogether.
readLines(observed2)

# WORKING: rsvg to bitmap works as expected as per fix of #35
bitmap = rsvg::rsvg(charToRaw(svg_text),width = 50,height = 50)
im <- magick::image_read(bitmap)
grid::grid.raster(im)

# WORKING: as does rsvg::rsvg_png which is fine...
observed3 = tempfile(fileext = ".observed.png")
rsvg::rsvg_png(charToRaw(svg_text),file = observed3,width = 50,height = 50)
rstudioapi::viewer(observed3)

# NOT WORKING: rsvg::rsvg_ps is also not working.
observed4 = tempfile(fileext = ".observed.ps")
rsvg::rsvg_ps(charToRaw(svg_text),file = observed4,width = 50,height = 50)
rstudioapi::viewer(observed4)

# sessionInfo()
# R version 4.2.2 Patched (2022-11-10 r83330)
# Platform: x86_64-pc-linux-gnu (64-bit)
# Running under: Ubuntu 22.04.1 LTS
#
# Matrix products: default
# BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0
# LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0
#
# locale:
#   [1] LC_CTYPE=en_GB.UTF-8       LC_NUMERIC=C               LC_TIME=en_GB.UTF-8        LC_COLLATE=en_GB.UTF-8     LC_MONETARY=en_GB.UTF-8    LC_MESSAGES=en_GB.UTF-8    LC_PAPER=en_GB.UTF-8       LC_NAME=C                  LC_ADDRESS=C
# [10] LC_TELEPHONE=C             LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C
#
# attached base packages:
#   [1] stats     graphics  grDevices datasets  utils     methods   base
#
# other attached packages:
#   [1] rsvg_2.4.0

N.B. my librsvg2-2 is at version 2.52.2+dfsg-3 if that is relevant

file1532e38e37382.expected.pdf file1532e378b02d1.observed.pdf

I had a dig into the code - it seems to be something specific about the behaviour of surfaces from cairo_image_surface_create that is different from those from cairo_*_surface_create_for_stream but I'm perplexed as to what. Maybe there is some fundamental difference between raster and vector outputs? Or maybe the streaming surfaces are somehow different...?