emacs-diffs
[Top][All Lists]
Advanced

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

master b42481e 2/2: Fix SVG image dimension calculations (bug#44065)


From: Alan Third
Subject: master b42481e 2/2: Fix SVG image dimension calculations (bug#44065)
Date: Thu, 22 Oct 2020 15:28:39 -0400 (EDT)

branch: master
commit b42481e22eb1c1adfcef419d45bf9733837684cb
Author: Alan Third <alan@idiocy.org>
Commit: Alan Third <alan@idiocy.org>

    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.
    * etc/PROBLEMS: Describe the problem with librsvg 2.45 and below.
---
 etc/PROBLEMS |  4 ++++
 src/image.c  | 46 ++++++++++++++++++++++++++++++++--------------
 2 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index 41d5ea1..8ed92ab 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -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
diff --git a/src/image.c b/src/image.c
index 25d5af8..5f6d9f4 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,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.  */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]