From f45ce78c40e37bf2aab83d2d1183ed896c5c1c4c Mon Sep 17 00:00:00 2001 From: Zajcev Evgeny Date: Thu, 3 Dec 2020 18:37:18 +0300 Subject: [PATCH] Explicitly specify svg base_uri using `:base-uri' image property * src/image.c (svg_load): Check `:base-uri' image property to explicitly set base_uri for images embedded into SVG (enum svg_keyword_index): (svg_format): Add :base-uri. * lisp/svg.el (svg-embed-base-uri-image): New function to embed images located relative to images `:base-uri' --- doc/lispref/display.texi | 20 ++++++++++++++++++++ etc/NEWS | 12 ++++++++++++ lisp/svg.el | 13 +++++++++++++ src/image.c | 21 ++++++++++++++------- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index b9b05a2a422..2b3119ea590 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5900,6 +5900,26 @@ string containing the image data as raw bytes. @var{image-type} should be a @end lisp @end defun +@defun svg-embed-base-uri-image svg relative-filename &rest args +To @var{svg} add an embedded (raster) image placed at +@var{relative-filename}. @var{relative-filename} is searched inside +@code{file-name-directory} of the @code{:base-uri} svg image property. +This improves the performance of embedding large images. + +@lisp +;; Embeding /tmp/subdir/rms.jpg and /tmp/another/rms.jpg +(svg-embed-base-uri-image svg "subdir/rms.jpg" + :width "100px" :height "100px" + :x "50px" :y "75px") +(svg-embed-base-uri-image svg "another/rms.jpg" + :width "100px" :height "100px" + :x "75px" :y "50px") +(svg-image svg :scale 1.0 + :base-uri "/tmp/dummy" + :width 175 :height 175) +@end lisp +@end defun + @defun svg-clip-path svg &rest args Add a clipping path to @var{svg}. If applied to a shape via the @var{:clip-path} property, parts of that shape which lie outside of diff --git a/etc/NEWS b/etc/NEWS index 9aa735da726..901a432d99e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1111,6 +1111,18 @@ If 'shr-width' is non-nil, it overrides this variable. ** Images +--- +** Can explicitly specify base_uri for svg images. +':base-uri' image property can be used to explicitly specify base_uri +for embedded images into svg. ':base-uri' is supported for both file +and data svg images. + ++++ +** 'svg-embed-base-uri-image' added to embed images +'svg-embed-base-uri-image' can be used to embed images located +relatively to 'file-name-directory' of the ':base-uri' svg image property. +This works much faster then 'svg-embed'. + +++ *** New function 'image-cache-size'. This function returns the size of the current image cache, in bytes. diff --git a/lisp/svg.el b/lisp/svg.el index eeb945f53b5..1ca59658aa7 100644 --- a/lisp/svg.el +++ b/lisp/svg.el @@ -184,6 +184,19 @@ otherwise. IMAGE-TYPE should be a MIME image type, like `((xlink:href . ,(svg--image-data image image-type datap)) ,@(svg--arguments svg args))))) +(defun svg-embed-base-uri-image (svg relative-filename &rest args) + "Insert image placed at RELATIVE-FILENAME into the SVG structure. +RELATIVE-FILENAME will be searched in `file-name-directory' of the +image's `:base-uri' property. If `:base-uri' is not specified for the +image, then embedding won't work. Embedding large images using this +function is much faster than `svg-embed'." + (svg--append + svg + (dom-node + 'image + `((xlink:href . ,relative-filename) + ,@(svg--arguments svg args))))) + (defun svg-text (svg text &rest args) "Add TEXT to SVG." (svg--append diff --git a/src/image.c b/src/image.c index 54380d1cdfa..6b85ab78f61 100644 --- a/src/image.c +++ b/src/image.c @@ -9492,6 +9492,7 @@ enum svg_keyword_index SVG_TYPE, SVG_DATA, SVG_FILE, + SVG_BASE_URI, SVG_ASCENT, SVG_MARGIN, SVG_RELIEF, @@ -9511,6 +9512,7 @@ static const struct image_keyword svg_format[SVG_LAST] = {":type", IMAGE_SYMBOL_VALUE, 1}, {":data", IMAGE_STRING_VALUE, 0}, {":file", IMAGE_STRING_VALUE, 0}, + {":base-uri", IMAGE_STRING_VALUE, 0}, {":ascent", IMAGE_ASCENT_VALUE, 0}, {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, {":relief", IMAGE_INTEGER_VALUE, 0}, @@ -9743,10 +9745,11 @@ static bool svg_load (struct frame *f, struct image *img) { bool success_p = 0; - Lisp_Object file_name; + Lisp_Object file_name, base_uri; /* If IMG->spec specifies a file name, create a non-file spec from it. */ file_name = image_spec_value (img->spec, QCfile, NULL); + base_uri = image_spec_value (img->spec, QCbase_uri, NULL); if (STRINGP (file_name)) { int fd; @@ -9766,15 +9769,16 @@ svg_load (struct frame *f, struct image *img) return 0; } /* If the file was slurped into memory properly, parse it. */ - success_p = svg_load_image (f, img, contents, size, - SSDATA (ENCODE_FILE (file))); + if (!STRINGP (base_uri)) + base_uri = ENCODE_FILE (file); + success_p = svg_load_image (f, img, contents, size, SSDATA (base_uri)); xfree (contents); } /* Else it's not a file, it's a Lisp object. Load the image from a Lisp object rather than a file. */ else { - Lisp_Object data, original_filename; + Lisp_Object data; data = image_spec_value (img->spec, QCdata, NULL); if (!STRINGP (data)) @@ -9782,10 +9786,10 @@ svg_load (struct frame *f, struct image *img) image_error ("Invalid image data `%s'", data); return 0; } - original_filename = BVAR (current_buffer, filename); + if (!STRINGP (base_uri)) + base_uri = BVAR (current_buffer, filename); success_p = svg_load_image (f, img, SSDATA (data), SBYTES (data), - (NILP (original_filename) ? NULL - : SSDATA (original_filename))); + (NILP (base_uri) ? NULL : SSDATA (base_uri))); } return success_p; @@ -9886,6 +9890,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, FRAME_DISPLAY_INFO (f)->resy); /* Set base_uri for properly handling referenced images (via 'href'). + Can be explicitly specified using `:base_uri' image property. See rsvg bug 596114 - "image refs are relative to curdir, not .svg file" . */ if (filename) @@ -10058,6 +10063,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, FRAME_DISPLAY_INFO (f)->resy); /* Set base_uri for properly handling referenced images (via 'href'). + Can be explicitly specified using `:base_uri' image property. See rsvg bug 596114 - "image refs are relative to curdir, not .svg file" . */ if (filename) @@ -10740,6 +10746,7 @@ non-numeric, there is no explicit limit on the size of images. */); #if defined (HAVE_RSVG) DEFSYM (Qsvg, "svg"); + DEFSYM (QCbase_uri, ":base-uri"); add_image_type (Qsvg); #ifdef HAVE_NTGUI /* Other libraries used directly by svg code. */ -- 2.39.2