diff options
| author | Alan Third | 2020-10-25 15:45:07 +0000 |
|---|---|---|
| committer | Alan Third | 2020-11-09 14:49:51 +0000 |
| commit | 4469e0de011c2c5862f6c1c970b9ad1dfbbda496 (patch) | |
| tree | 5b344714a3cee87296cc3b27d51c1d1a26deb8bb /src | |
| parent | 8dc237270f88a6abce4df9a1235b38288792ab71 (diff) | |
| download | emacs-4469e0de011c2c5862f6c1c970b9ad1dfbbda496.tar.gz emacs-4469e0de011c2c5862f6c1c970b9ad1dfbbda496.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/image.c | 102 |
1 files changed, 97 insertions, 5 deletions
diff --git a/src/image.c b/src/image.c index c857b8e62a4..b4cb1b7bf83 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -9545,6 +9545,9 @@ DEF_DLL_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **)); | |||
| 9545 | #endif | 9545 | #endif |
| 9546 | 9546 | ||
| 9547 | #if LIBRSVG_CHECK_VERSION (2, 46, 0) | 9547 | #if LIBRSVG_CHECK_VERSION (2, 46, 0) |
| 9548 | DEF_DLL_FN (void, rsvg_handle_get_intrinsic_dimensions, | ||
| 9549 | RsvgHandle *, gboolean *, RsvgLength *, gboolean *, | ||
| 9550 | RsvgLength *, gboolean *, RsvgRectangle *)); | ||
| 9548 | DEF_DLL_FN (gboolean, rsvg_handle_get_geometry_for_layer, | 9551 | DEF_DLL_FN (gboolean, rsvg_handle_get_geometry_for_layer, |
| 9549 | (RsvgHandle *, const char *, const RsvgRectangle *, | 9552 | (RsvgHandle *, const char *, const RsvgRectangle *, |
| 9550 | RsvgRectangle *, RsvgRectangle *, GError **)); | 9553 | RsvgRectangle *, RsvgRectangle *, GError **)); |
| @@ -9599,6 +9602,7 @@ init_svg_functions (void) | |||
| 9599 | LOAD_DLL_FN (library, rsvg_handle_close); | 9602 | LOAD_DLL_FN (library, rsvg_handle_close); |
| 9600 | #endif | 9603 | #endif |
| 9601 | #if LIBRSVG_CHECK_VERSION (2, 46, 0) | 9604 | #if LIBRSVG_CHECK_VERSION (2, 46, 0) |
| 9605 | LOAD_DLL_FN (library, rsvg_handle_get_intrinsic_dimensions); | ||
| 9602 | LOAD_DLL_FN (library, rsvg_handle_get_geometry_for_layer); | 9606 | LOAD_DLL_FN (library, rsvg_handle_get_geometry_for_layer); |
| 9603 | #else | 9607 | #else |
| 9604 | LOAD_DLL_FN (library, rsvg_handle_get_dimensions); | 9608 | LOAD_DLL_FN (library, rsvg_handle_get_dimensions); |
| @@ -9742,6 +9746,44 @@ svg_load (struct frame *f, struct image *img) | |||
| 9742 | return success_p; | 9746 | return success_p; |
| 9743 | } | 9747 | } |
| 9744 | 9748 | ||
| 9749 | static double | ||
| 9750 | svg_css_length_to_pixels (RsvgLength length) | ||
| 9751 | { | ||
| 9752 | /* FIXME: 96 appears to be a pretty standard DPI but we should | ||
| 9753 | probably use the real DPI if we can get it. */ | ||
| 9754 | double dpi = 96; | ||
| 9755 | double value = length.length; | ||
| 9756 | |||
| 9757 | switch (length.unit) | ||
| 9758 | { | ||
| 9759 | case RSVG_UNIT_PX: | ||
| 9760 | /* Already a pixel value. */ | ||
| 9761 | break; | ||
| 9762 | case RSVG_UNIT_CM: | ||
| 9763 | /* 2.54 cm in an inch. */ | ||
| 9764 | value = dpi * value / 2.54; | ||
| 9765 | case RSVG_UNIT_MM: | ||
| 9766 | /* 25.4 mm in an inch. */ | ||
| 9767 | value = dpi * value / 25.4; | ||
| 9768 | break; | ||
| 9769 | case RSVG_UNIT_PT: | ||
| 9770 | /* 72 points in an inch. */ | ||
| 9771 | value = dpi * value / 72; | ||
| 9772 | case RSVG_UNIT_PC: | ||
| 9773 | /* 6 picas in an inch. */ | ||
| 9774 | value = dpi * value / 6; | ||
| 9775 | case RSVG_UNIT_IN: | ||
| 9776 | value *= dpi; | ||
| 9777 | break; | ||
| 9778 | default: | ||
| 9779 | /* Probably one of em, ex, or %. We can't know what the pixel | ||
| 9780 | value is without more information. */ | ||
| 9781 | value = 0; | ||
| 9782 | } | ||
| 9783 | |||
| 9784 | return value; | ||
| 9785 | } | ||
| 9786 | |||
| 9745 | /* Load frame F and image IMG. CONTENTS contains the SVG XML data to | 9787 | /* Load frame F and image IMG. CONTENTS contains the SVG XML data to |
| 9746 | be parsed, SIZE is its size, and FILENAME is the name of the SVG | 9788 | be parsed, SIZE is its size, and FILENAME is the name of the SVG |
| 9747 | file being loaded. | 9789 | file being loaded. |
| @@ -9810,11 +9852,48 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9810 | #if LIBRSVG_CHECK_VERSION (2, 46, 0) | 9852 | #if LIBRSVG_CHECK_VERSION (2, 46, 0) |
| 9811 | RsvgRectangle zero_rect, viewbox, out_logical_rect; | 9853 | RsvgRectangle zero_rect, viewbox, out_logical_rect; |
| 9812 | 9854 | ||
| 9813 | rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL, | 9855 | /* Try the instrinsic dimensions first. */ |
| 9814 | &zero_rect, &viewbox, | 9856 | gboolean has_width, has_height, has_viewbox; |
| 9815 | &out_logical_rect, NULL); | 9857 | RsvgLength iwidth, iheight; |
| 9816 | viewbox_width = viewbox.x + viewbox.width; | 9858 | |
| 9817 | viewbox_height = viewbox.y + viewbox.height; | 9859 | rsvg_handle_get_intrinsic_dimensions (rsvg_handle, |
| 9860 | &has_width, &iwidth, | ||
| 9861 | &has_height, &iheight, | ||
| 9862 | &has_viewbox, &viewbox); | ||
| 9863 | |||
| 9864 | if (has_width && has_height) | ||
| 9865 | { | ||
| 9866 | /* Success! We can use these values directly. */ | ||
| 9867 | viewbox_width = svg_css_length_to_pixels (iwidth); | ||
| 9868 | viewbox_height = svg_css_length_to_pixels (iheight); | ||
| 9869 | } | ||
| 9870 | else if (has_width && has_viewbox) | ||
| 9871 | { | ||
| 9872 | viewbox_width = svg_css_length_to_pixels (iwidth); | ||
| 9873 | viewbox_height = svg_css_length_to_pixels (iwidth) | ||
| 9874 | * viewbox.width / viewbox.height; | ||
| 9875 | } | ||
| 9876 | else if (has_height && has_viewbox) | ||
| 9877 | { | ||
| 9878 | viewbox_height = svg_css_length_to_pixels (iheight); | ||
| 9879 | viewbox_width = svg_css_length_to_pixels (iheight) | ||
| 9880 | * viewbox.height / viewbox.width; | ||
| 9881 | } | ||
| 9882 | else if (has_viewbox) | ||
| 9883 | { | ||
| 9884 | viewbox_width = viewbox.width; | ||
| 9885 | viewbox_height = viewbox.height; | ||
| 9886 | } | ||
| 9887 | else | ||
| 9888 | { | ||
| 9889 | /* We haven't found a useable set of sizes, so try working out | ||
| 9890 | the visible area. */ | ||
| 9891 | rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL, | ||
| 9892 | &zero_rect, &viewbox, | ||
| 9893 | &out_logical_rect, NULL); | ||
| 9894 | viewbox_width = viewbox.x + viewbox.width; | ||
| 9895 | viewbox_height = viewbox.y + viewbox.height; | ||
| 9896 | } | ||
| 9818 | #else | 9897 | #else |
| 9819 | /* The function used above to get the geometry of the visible area | 9898 | /* The function used above to get the geometry of the visible area |
| 9820 | of the SVG are only available in librsvg 2.46 and above, so in | 9899 | 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, | |||
| 9827 | viewbox_width = dimension_data.width; | 9906 | viewbox_width = dimension_data.width; |
| 9828 | viewbox_height = dimension_data.height; | 9907 | viewbox_height = dimension_data.height; |
| 9829 | #endif | 9908 | #endif |
| 9909 | |||
| 9910 | if (viewbox_width == 0 || viewbox_height == 0) | ||
| 9911 | { | ||
| 9912 | /* We do not have any usable dimensions, so make some up. The | ||
| 9913 | values below are supposedly the default values most web | ||
| 9914 | browsers use for SVGs with no set size. */ | ||
| 9915 | /* FIXME: At this stage we should perhaps consider rendering the | ||
| 9916 | image out to a bitmap and getting the dimensions from | ||
| 9917 | that. */ | ||
| 9918 | viewbox_width = 300; | ||
| 9919 | viewbox_height = 150; | ||
| 9920 | } | ||
| 9921 | |||
| 9830 | compute_image_size (viewbox_width, viewbox_height, img->spec, | 9922 | compute_image_size (viewbox_width, viewbox_height, img->spec, |
| 9831 | &width, &height); | 9923 | &width, &height); |
| 9832 | 9924 | ||