[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. */