diff options
| author | Alan Third | 2023-08-05 10:39:31 +0100 |
|---|---|---|
| committer | Alan Third | 2023-08-08 22:14:45 +0100 |
| commit | 66a3bb36f940d2f2a712d20aadaeda20b8792cff (patch) | |
| tree | 7f7edc21d301e28aa65c8a0e0ff13dd935b3b557 | |
| parent | 72e24ed0316542184f40c05eda2bf7c77808ec0c (diff) | |
| download | emacs-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.c | 82 |
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; |