aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Third2023-08-05 10:39:31 +0100
committerAlan Third2023-08-08 22:14:45 +0100
commit66a3bb36f940d2f2a712d20aadaeda20b8792cff (patch)
tree7f7edc21d301e28aa65c8a0e0ff13dd935b3b557
parent72e24ed0316542184f40c05eda2bf7c77808ec0c (diff)
downloademacs-66a3bb36f940d2f2a712d20aadaeda20b8792cff.tar.gz
emacs-66a3bb36f940d2f2a712d20aadaeda20b8792cff.zip
Fix percentage sizes in SVG display (bug#64908)
* src/image.c (svg_css_length_to_pixels): Make percent units always return zero and handle font size based units better. (svg_load_image): Don't rely on the width and height values from the SVG actually having any useful data, even if they're explicitly set.
-rw-r--r--src/image.c82
1 files changed, 52 insertions, 30 deletions
diff --git a/src/image.c b/src/image.c
index 06fc44b5abd..29e88f0d752 100644
--- a/src/image.c
+++ b/src/image.c
@@ -11740,6 +11740,12 @@ svg_css_length_to_pixels (RsvgLength length, double dpi, int font_size)
11740{ 11740{
11741 double value = length.length; 11741 double value = length.length;
11742 11742
11743#if ! LIBRSVG_CHECK_VERSION (2, 48, 0)
11744 /* librsvg 2.48 lets us define the font size, but earlier versions
11745 default to 12 pixels. */
11746 font_size = 12;
11747#endif
11748
11743 switch (length.unit) 11749 switch (length.unit)
11744 { 11750 {
11745 case RSVG_UNIT_PX: 11751 case RSVG_UNIT_PX:
@@ -11764,16 +11770,31 @@ svg_css_length_to_pixels (RsvgLength length, double dpi, int font_size)
11764 case RSVG_UNIT_IN: 11770 case RSVG_UNIT_IN:
11765 value *= dpi; 11771 value *= dpi;
11766 break; 11772 break;
11767#if LIBRSVG_CHECK_VERSION (2, 48, 0)
11768 /* We don't know exactly what font size is used on older librsvg
11769 versions. */
11770 case RSVG_UNIT_EM: 11773 case RSVG_UNIT_EM:
11771 value *= font_size; 11774 value *= font_size;
11772 break; 11775 break;
11773#endif 11776 case RSVG_UNIT_EX:
11777 /* librsvg uses an ex height of half the em height, so we match
11778 that here. */
11779 value = value * font_size / 2.0;
11780 break;
11781 case RSVG_UNIT_PERCENT:
11782 /* Percent is a ratio of the containing "viewport". We don't
11783 have a viewport, as such, as we try to draw the image to it's
11784 'natural' size rather than dictate the size as if we were
11785 drawing icons on a toolbar or similar. This means that
11786 percent values are useless to us and we are best off just
11787 drawing the image according to whatever other sizes we can
11788 derive.
11789
11790 If we do set explicit width and height values in the image
11791 spec, this will work out correctly as librsvg will still
11792 honour the percentage sizes in its final rendering no matter
11793 what size we make the image. */
11794 value = 0;
11795 break;
11774 default: 11796 default:
11775 /* Probably ex or %. We can't know what the pixel value is 11797 /* We should never reach this. */
11776 without more information. */
11777 value = 0; 11798 value = 0;
11778 } 11799 }
11779 11800
@@ -11904,7 +11925,8 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
11904 } 11925 }
11905 else 11926 else
11906 { 11927 {
11907 RsvgRectangle zero_rect, viewbox, out_logical_rect; 11928 RsvgRectangle viewbox;
11929 double explicit_width = 0, explicit_height = 0;
11908 11930
11909 /* Try the intrinsic dimensions first. */ 11931 /* Try the intrinsic dimensions first. */
11910 gboolean has_width, has_height; 11932 gboolean has_width, has_height;
@@ -11916,34 +11938,27 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
11916 &has_height, &iheight, 11938 &has_height, &iheight,
11917 &has_viewbox, &viewbox); 11939 &has_viewbox, &viewbox);
11918 11940
11919 if (has_width && has_height) 11941 if (has_width)
11920 { 11942 explicit_width = svg_css_length_to_pixels (iwidth, dpi,
11921 /* Success! We can use these values directly. */ 11943 img->face_font_size);
11922 viewbox_width = svg_css_length_to_pixels (iwidth, dpi, 11944 if (has_height)
11945 explicit_height = svg_css_length_to_pixels (iheight, dpi,
11923 img->face_font_size); 11946 img->face_font_size);
11924 viewbox_height = svg_css_length_to_pixels (iheight, dpi,
11925 img->face_font_size);
11926 11947
11927 /* Here one dimension could be zero because in percent unit. 11948 if (explicit_width > 0 && explicit_height > 0)
11928 So calculate this dimension with the other. */ 11949 {
11929 if (! (0 < viewbox_width) && (iwidth.unit == RSVG_UNIT_PERCENT)) 11950 viewbox_width = explicit_width;
11930 viewbox_width = (viewbox_height * viewbox.width / viewbox.height) 11951 viewbox_height = explicit_height;
11931 * iwidth.length;
11932 else if (! (0 < viewbox_height) && (iheight.unit == RSVG_UNIT_PERCENT))
11933 viewbox_height = (viewbox_width * viewbox.height / viewbox.width)
11934 * iheight.length;
11935 } 11952 }
11936 else if (has_width && has_viewbox) 11953 else if (explicit_width > 0 && has_viewbox)
11937 { 11954 {
11938 viewbox_width = svg_css_length_to_pixels (iwidth, dpi, 11955 viewbox_width = explicit_width;
11939 img->face_font_size); 11956 viewbox_height = explicit_width * viewbox.height / viewbox.width;
11940 viewbox_height = viewbox_width * viewbox.height / viewbox.width;
11941 } 11957 }
11942 else if (has_height && has_viewbox) 11958 else if (explicit_height > 0 && has_viewbox)
11943 { 11959 {
11944 viewbox_height = svg_css_length_to_pixels (iheight, dpi, 11960 viewbox_height = explicit_height;
11945 img->face_font_size); 11961 viewbox_width = explicit_height * viewbox.width / viewbox.height;
11946 viewbox_width = viewbox_height * viewbox.width / viewbox.height;
11947 } 11962 }
11948 else if (has_viewbox) 11963 else if (has_viewbox)
11949 { 11964 {
@@ -11957,8 +11972,15 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
11957 { 11972 {
11958 /* We haven't found a usable set of sizes, so try working out 11973 /* We haven't found a usable set of sizes, so try working out
11959 the visible area. */ 11974 the visible area. */
11975
11976 /* FIXME: I'm not sure exactly how librsvg uses this
11977 viewport input here, so I'm not sure what values I should
11978 set. */
11979 RsvgRectangle max_viewport_rect = {0, 0, UINT_MAX, UINT_MAX};
11980 RsvgRectangle out_logical_rect;
11981
11960 rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL, 11982 rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL,
11961 &zero_rect, &viewbox, 11983 &max_viewport_rect, &viewbox,
11962 &out_logical_rect, NULL); 11984 &out_logical_rect, NULL);
11963 viewbox_width = viewbox.x + viewbox.width; 11985 viewbox_width = viewbox.x + viewbox.width;
11964 viewbox_height = viewbox.y + viewbox.height; 11986 viewbox_height = viewbox.y + viewbox.height;