]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix SVG image dimension calculations (bug#44065)
authorAlan Third <alan@idiocy.org>
Mon, 19 Oct 2020 20:19:57 +0000 (21:19 +0100)
committerAlan Third <alan@idiocy.org>
Thu, 22 Oct 2020 19:05:59 +0000 (20:05 +0100)
* src/image.c (svg_load_image): Calculate the image size by using the
viewBox size and applying it to the image.
* etc/PROBLEMS: Describe the problem with librsvg 2.45 and below.

etc/PROBLEMS
src/image.c

index 41d5ea1bb751f4ead6b29c97e735c8c700c13240..8ed92ab75e06660f7df5e9bc2ceeefdaa414651e 100644 (file)
@@ -181,6 +181,10 @@ Configure checks for the correct version, but this problem could occur
 if a binary built against a shared libungif is run on a system with an
 older version.
 
+** SVG images may be cropped incorrectly with librsvg 2.45 and below.
+Librsvg 2.46 and above have improved geometry code which Emacs is able
+to take advantage of.
+
 ** Emacs aborts inside the function 'tparam1'.
 
 This can happen if Emacs was built without terminfo support, but the
index 25d5af8a8d55f3a8dcdd73549daf1ad1e96ced20..5f6d9f4c44340c06fcfb64e28d6c61246d021ffa 100644 (file)
@@ -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,38 @@ 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
+  /* The function used above to get the geometry of the visible area
+     of the SVG are only available in librsvg 2.46 and above, so in
+     certain circumstances this code path can result in some parts of
+     the SVG being cropped.  */
+  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 +9843,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 +9868,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 +9911,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.  */