emacs-diffs
[Top][All Lists]
Advanced

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

master 4469e0d 1/3: Calculate SVG image sizes more accurately (bug#44206


From: Alan Third
Subject: master 4469e0d 1/3: Calculate SVG image sizes more accurately (bug#44206)
Date: Mon, 9 Nov 2020 09:54:09 -0500 (EST)

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

    Calculate SVG image sizes more accurately (bug#44206)
    
    * src/image.c (svg_css_length_to_pixels): New function.
    (svg_load_image): Try more methods to work out the image size.
---
 src/image.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 97 insertions(+), 5 deletions(-)

diff --git a/src/image.c b/src/image.c
index c857b8e..b4cb1b7 100644
--- a/src/image.c
+++ b/src/image.c
@@ -9545,6 +9545,9 @@ DEF_DLL_FN (gboolean, rsvg_handle_close, (RsvgHandle *, 
GError **));
 #endif
 
 #if LIBRSVG_CHECK_VERSION (2, 46, 0)
+DEF_DLL_FN (void, rsvg_handle_get_intrinsic_dimensions,
+            RsvgHandle *, gboolean *, RsvgLength *, gboolean *,
+            RsvgLength *, gboolean *, RsvgRectangle *));
 DEF_DLL_FN (gboolean, rsvg_handle_get_geometry_for_layer,
            (RsvgHandle *, const char *, const RsvgRectangle *,
             RsvgRectangle *, RsvgRectangle *, GError **));
@@ -9599,6 +9602,7 @@ init_svg_functions (void)
   LOAD_DLL_FN (library, rsvg_handle_close);
 #endif
 #if LIBRSVG_CHECK_VERSION (2, 46, 0)
+  LOAD_DLL_FN (library, rsvg_handle_get_intrinsic_dimensions);
   LOAD_DLL_FN (library, rsvg_handle_get_geometry_for_layer);
 #else
   LOAD_DLL_FN (library, rsvg_handle_get_dimensions);
@@ -9742,6 +9746,44 @@ svg_load (struct frame *f, struct image *img)
   return success_p;
 }
 
+static double
+svg_css_length_to_pixels (RsvgLength length)
+{
+  /* FIXME: 96 appears to be a pretty standard DPI but we should
+     probably use the real DPI if we can get it.  */
+  double dpi = 96;
+  double value = length.length;
+
+  switch (length.unit)
+    {
+    case RSVG_UNIT_PX:
+      /* Already a pixel value.  */
+      break;
+    case RSVG_UNIT_CM:
+      /* 2.54 cm in an inch.  */
+      value = dpi * value / 2.54;
+    case RSVG_UNIT_MM:
+      /* 25.4 mm in an inch.  */
+      value = dpi * value / 25.4;
+      break;
+    case RSVG_UNIT_PT:
+      /* 72 points in an inch.  */
+      value = dpi * value / 72;
+    case RSVG_UNIT_PC:
+      /* 6 picas in an inch.  */
+      value = dpi * value / 6;
+    case RSVG_UNIT_IN:
+      value *= dpi;
+      break;
+    default:
+      /* Probably one of em, ex, or %.  We can't know what the pixel
+         value is without more information.  */
+      value = 0;
+    }
+
+  return value;
+}
+
 /* Load frame F and image IMG.  CONTENTS contains the SVG XML data to
    be parsed, SIZE is its size, and FILENAME is the name of the SVG
    file being loaded.
@@ -9810,11 +9852,48 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
 #if LIBRSVG_CHECK_VERSION (2, 46, 0)
   RsvgRectangle zero_rect, viewbox, out_logical_rect;
 
-  rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL,
-                                      &zero_rect, &viewbox,
-                                      &out_logical_rect, NULL);
-  viewbox_width = viewbox.x + viewbox.width;
-  viewbox_height = viewbox.y + viewbox.height;
+  /* Try the instrinsic dimensions first.  */
+  gboolean has_width, has_height, has_viewbox;
+  RsvgLength iwidth, iheight;
+
+  rsvg_handle_get_intrinsic_dimensions (rsvg_handle,
+                                        &has_width, &iwidth,
+                                        &has_height, &iheight,
+                                        &has_viewbox, &viewbox);
+
+  if (has_width && has_height)
+    {
+      /* Success!  We can use these values directly.  */
+      viewbox_width = svg_css_length_to_pixels (iwidth);
+      viewbox_height = svg_css_length_to_pixels (iheight);
+    }
+  else if (has_width && has_viewbox)
+    {
+      viewbox_width = svg_css_length_to_pixels (iwidth);
+      viewbox_height = svg_css_length_to_pixels (iwidth)
+        * viewbox.width / viewbox.height;
+    }
+  else if (has_height && has_viewbox)
+    {
+      viewbox_height = svg_css_length_to_pixels (iheight);
+      viewbox_width = svg_css_length_to_pixels (iheight)
+        * viewbox.height / viewbox.width;
+    }
+  else if (has_viewbox)
+    {
+      viewbox_width = viewbox.width;
+      viewbox_height = viewbox.height;
+    }
+  else
+    {
+      /* We haven't found a useable set of sizes, so try working out
+         the visible area.  */
+      rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL,
+                                          &zero_rect, &viewbox,
+                                          &out_logical_rect, 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
@@ -9827,6 +9906,19 @@ svg_load_image (struct frame *f, struct image *img, char 
*contents,
   viewbox_width = dimension_data.width;
   viewbox_height = dimension_data.height;
 #endif
+
+  if (viewbox_width == 0 || viewbox_height == 0)
+    {
+      /* We do not have any usable dimensions, so make some up.  The
+         values below are supposedly the default values most web
+         browsers use for SVGs with no set size.  */
+      /* FIXME: At this stage we should perhaps consider rendering the
+         image out to a bitmap and getting the dimensions from
+         that.  */
+      viewbox_width = 300;
+      viewbox_height = 150;
+    }
+
   compute_image_size (viewbox_width, viewbox_height, img->spec,
                       &width, &height);
 



reply via email to

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