Subject: Re: bug#44065: 28.0.50; SVG image not shown completely

From: Alan Third <[email-masked]>
Date: Tue, 20 Oct 2020 13:31:45 +0100

On Mon, Oct 19, 2020 at 05:34:45PM -0500, Sheng Yang wrote:
> 
> > I've got something that works for me. I'm using 2.50, so I'd
> > appreciate it if someone using 2.45 or below could check that it
> > builds and isn't completely broken.
> 
> I checked the patch on Debian 10.6, with librsvg2 2.44.10-2.1. Compilation failed with the following error (path sanitized)
> 
> /usr/bin/ld: image.o: in function `svg_load_image':
> emacs/src/image.c:9810: undefined reference to `rsvg_handle_set_stylesheet'
> /usr/bin/ld: emacs/src/image.c:9924: undefined reference to `rsvg_handle_set_stylesheet'
> collect2: error: ld returned 1 exit status
> make[1]: *** [Makefile:651：temacs] error 1
> make[1]: leaving directory “emacs/src”
> make: *** [Makefile:424：src] error 2

Thanks. I've attached a new one that doesn't try playing with
stylesheets since that's not necessary for this fix.

> BTW, the patch fixes the problem on Arch Linux, with librsvg 2:2.50.1-1.

Excellent, good to know, thanks.
-- 
Alan Third
>From 760fe87e1dcb7451a5fa9ff19b80f940b8e03304 Mon Sep 17 00:00:00 2001
From: Alan Third <[email-masked]>
Date: Mon, 19 Oct 2020 21:19:57 +0100
Subject: [PATCH v2] Fix SVG image dimension calculations (bug#44065)

* src/image.c (svg_load_image): Calculate the image size by using the
viewBox size and applying it to the image.
---
 src/image.c | 42 ++++++++++++++++++++++++++++--------------
 1 file changed, 28 insertions(+), 14 deletions(-)

diff --git a/src/image.c b/src/image.c
index 25d5af8a8d..c734623739 100644
--- a/src/image.c
+++ b/src/image.c
@@ -9736,7 +9736,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
 		ptrdiff_t size, char *filename)
 {
   RsvgHandle *rsvg_handle;
-  RsvgDimensionData dimension_data;
+  double viewbox_width, viewbox_height;
   GError *err = NULL;
   GdkPixbuf *pixbuf;
   int width;
@@ -9789,15 +9789,34 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
 #endif
 
   /* Get the image dimensions.  */
+#if LIBRSVG_CHECK_VERSION (2, 46, 0)
+  RsvgRectangle zero_rect, viewbox;
+
+  rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL,
+                                      &zero_rect, &viewbox,
+                                      NULL, NULL);
+  viewbox_width = viewbox.x + viewbox.width;
+  viewbox_height = viewbox.y + viewbox.height;
+#else
+  RsvgDimensionData dimension_data;
+
   rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
 
+  viewbox_width = dimension_data.width;
+  viewbox_height = dimension_data.height;
+#endif
+  compute_image_size (viewbox_width, viewbox_height, img->spec,
+                      &width, &height);
+
+  if (! check_image_size (f, width, height))
+    {
+      image_size_error ();
+      goto rsvg_error;
+    }
+
   /* We are now done with the unmodified data.  */
   g_object_unref (rsvg_handle);
 
-  /* Calculate the final image size.  */
-  compute_image_size (dimension_data.width, dimension_data.height,
-                      img->spec, &width, &height);
-
   /* Wrap the SVG data in another SVG.  This allows us to set the
      width and height, as well as modify the foreground and background
      colors.  */
@@ -9820,7 +9839,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
       "xmlns:xi=\"http://www.w3.org/2001/XInclude\" "
       "style=\"color: #%06X; fill: currentColor;\" "
       "width=\"%d\" height=\"%d\" preserveAspectRatio=\"none\" "
-      "viewBox=\"0 0 %d %d\">"
+      "viewBox=\"0 0 %f %f\">"
       "<rect width=\"100%%\" height=\"100%%\" fill=\"#%06X\"/>"
       "<xi:include href=\"data:image/svg+xml;base64,%s\"></xi:include>"
       "</svg>";
@@ -9845,8 +9864,9 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
     if (!wrapped_contents
         || buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper,
                                     foreground & 0xFFFFFF, width, height,
-                                    dimension_data.width, dimension_data.height,
-                                    background & 0xFFFFFF, SSDATA (encoded_contents)))
+                                    viewbox_width, viewbox_height,
+                                    background & 0xFFFFFF,
+                                    SSDATA (encoded_contents)))
       goto rsvg_error;
 
     wrapped_size = strlen (wrapped_contents);
@@ -9887,12 +9907,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
   if (err) goto rsvg_error;
 #endif
 
-  rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
-  if (! check_image_size (f, dimension_data.width, dimension_data.height))
-    {
-      image_size_error ();
-      goto rsvg_error;
-    }
 
   /* We can now get a valid pixel buffer from the svg file, if all
      went ok.  */
-- 
2.26.1