]> git.eshelyaron.com Git - emacs.git/commitdiff
Set basic SVG attributes (bug#40845)
authorAlan Third <alan@idiocy.org>
Sun, 23 Aug 2020 15:28:17 +0000 (16:28 +0100)
committerAlan Third <alan@idiocy.org>
Sun, 23 Aug 2020 15:28:17 +0000 (16:28 +0100)
* test/manual/image-transforms-tests.el: Replace hard-coded colors
with defaults.
* src/dispextern.h (struct image):
* src/image.c (search_image_cache):
(xbm_load_image):
(xbm_load):
(pbm_load): Rename from frame to face where relevant.
(svg_load_image): Parse the image to find out the size, then wrap it
in another SVG to set a new size and colors, etc.
(lookup_image): Use the face colors instead of the frame colors.
(search_image_cache): Add ability to ignore the face colors.
(uncache_image): Uncache all copies of the image that share the spec,
even if the face colors don't match.
* etc/NEWS: Describe the changes.

etc/NEWS
lisp/net/shr.el
src/dispextern.h
src/gtkutil.c
src/image.c
src/nsmenu.m
src/xdisp.c
test/manual/image-transforms-tests.el

index d79cbe7611138164742916b2fbd9af780d6d2228..cff435684e58f8570b025fff89b3b0d177f778af 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -688,6 +688,22 @@ problematic in some contexts (like PDFs), so this list is now filtered
 based on 'auto-mode-alist'.  Only file names that map to 'image-mode'
 are now supported.
 
+---
+*** The background and foreground of images now default to face colors.
+When an image doesn't specify a foreground or background color, Emacs
+now uses colors from the face used to draw the surrounding text
+instead of the frame's default colors.
+
+To load images with the default frame colors use the ':foreground' and
+':background' image attributes, for example:
+
+    (create-image "filename" nil nil
+                  :foreground (face-attribute 'default :foreground)
+                  :background (face-attribute 'default :background))
+
+This change only affects image types that support foreground and
+background colors or transparency, such as xbm, pbm, svg, png and gif.
+
 ** EWW
 
 +++
index ddd811272135762a6053a51f069e3f980abcddc1..24595301b7985b562da0efdaea19ad1d1e6e197f 100644 (file)
@@ -1209,25 +1209,8 @@ Return a string with image data."
             ;; that are non-ASCII.
            (shr-dom-to-xml
             (libxml-parse-xml-region (point) (point-max)) 'utf-8)))
-    ;; SVG images often do not have a specified foreground/background
-    ;; color, so wrap them in styles.
-    (when (and (display-images-p)
-               (eq content-type 'image/svg+xml))
-      (setq data (svg--wrap-svg data)))
     (list data content-type)))
 
-(defun svg--wrap-svg (data)
-  "Add a default foreground colour to SVG images."
-  (let ((size (image-size (create-image data nil t :scaling 1) t)))
-    (with-temp-buffer
-      (insert
-       (format
-        "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xi=\"http://www.w3.org/2001/XInclude\" style=\"color: %s;\" viewBox=\"0 0 %d %d\"> <xi:include href=\"data:image/svg+xml;base64,%s\"></xi:include></svg>"
-        (face-foreground 'default)
-        (car size) (cdr size)
-        (base64-encode-string data t)))
-      (buffer-string))))
-
 (defun shr-image-displayer (content-function)
   "Return a function to display an image.
 CONTENT-FUNCTION is a function to retrieve an image for a cid url that
index 311867a0c8cb4d7b4b14740f5864ad8fa95c9348..956ca96eb619f6e31cf13e0dbf98740fe517f759 100644 (file)
@@ -3056,9 +3056,9 @@ struct image
      if necessary.  */
   unsigned long background;
 
-  /* Foreground and background colors of the frame on which the image
+  /* Foreground and background colors of the face on which the image
      is created.  */
-  unsigned long frame_foreground, frame_background;
+  unsigned long face_foreground, face_background;
 
   /* True if this image has a `transparent' background -- that is, is
      uses an image mask.  The accessor macro for this is
@@ -3475,7 +3475,7 @@ void clear_image_caches (Lisp_Object);
 void mark_image_cache (struct image_cache *);
 bool valid_image_p (Lisp_Object);
 void prepare_image_for_display (struct frame *, struct image *);
-ptrdiff_t lookup_image (struct frame *, Lisp_Object);
+ptrdiff_t lookup_image (struct frame *, Lisp_Object, int);
 
 #if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_NS
 #define RGB_PIXEL_COLOR unsigned long
index 1fe160acca9424b1dd170bf08b0675fe7d6e7408..fafd94c0f710821834d37eefaaabab44443d1f1d 100644 (file)
@@ -5113,7 +5113,7 @@ update_frame_tool_bar (struct frame *f)
           else
             idx = -1;
 
-          img_id = lookup_image (f, image);
+          img_id = lookup_image (f, image, -1);
           img = IMAGE_FROM_ID (f, img_id);
           prepare_image_for_display (f, img);
 
index 123de54ba27af1058933c60f271ddf1e226154e2..e8e3388c6bba2a3cf28e0c84288a1e0f3dd9cced 100644 (file)
@@ -1081,7 +1081,7 @@ calling this function.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = decode_window_system_frame (frame);
-      ptrdiff_t id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec, -1);
       struct image *img = IMAGE_FROM_ID (f, id);
       int width = img->width + 2 * img->hmargin;
       int height = img->height + 2 * img->vmargin;
@@ -1111,7 +1111,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = decode_window_system_frame (frame);
-      ptrdiff_t id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec, -1);
       struct image *img = IMAGE_FROM_ID (f, id);
       if (img->mask)
        mask = Qt;
@@ -1134,7 +1134,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = decode_window_system_frame (frame);
-      ptrdiff_t id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec, -1);
       struct image *img = IMAGE_FROM_ID (f, id);
       ext = img->lisp_data;
     }
@@ -1611,7 +1611,9 @@ equal_lists (Lisp_Object a, Lisp_Object b)
 /* Find an image matching SPEC in the cache, and return it.  If no
    image is found, return NULL.  */
 static struct image *
-search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
+search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash,
+                    unsigned long foreground, unsigned long background,
+                    bool ignore_colors)
 {
   struct image *img;
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
@@ -1634,8 +1636,8 @@ search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
   for (img = c->buckets[i]; img; img = img->next)
     if (img->hash == hash
        && equal_lists (img->spec, spec)
-       && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
-       && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
+       && (ignore_colors || (img->face_foreground == foreground
+                              && img->face_background == background)))
       break;
   return img;
 }
@@ -1646,8 +1648,13 @@ search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
 static void
 uncache_image (struct frame *f, Lisp_Object spec)
 {
-  struct image *img = search_image_cache (f, spec, sxhash (spec));
-  if (img)
+  struct image *img;
+
+  /* Because the background colors are based on the current face, we
+     can have multiple copies of an image with the same spec. We want
+     to remove them all to ensure the user doesn't see an old version
+     of the image when the face changes.  */
+  while ((img = search_image_cache (f, spec, sxhash (spec), 0, 0, true)))
     {
       free_image (f, img);
       /* As display glyphs may still be referring to the image ID, we
@@ -2133,7 +2140,17 @@ image_set_transform (struct frame *f, struct image *img)
 
   /* Determine size.  */
   int width, height;
-  compute_image_size (img->width, img->height, img->spec, &width, &height);
+
+#ifdef HAVE_RSVG
+  /* SVGs are pre-scaled to the correct size.  */
+  if (EQ (image_spec_value (img->spec, QCtype, NULL), Qsvg))
+    {
+      width = img->width;
+      height = img->height;
+    }
+  else
+#endif
+    compute_image_size (img->width, img->height, img->spec, &width, &height);
 
   /* Determine rotation.  */
   double rotation = 0.0;
@@ -2312,11 +2329,16 @@ image_set_transform (struct frame *f, struct image *img)
    SPEC must be a valid Lisp image specification (see valid_image_p).  */
 
 ptrdiff_t
-lookup_image (struct frame *f, Lisp_Object spec)
+lookup_image (struct frame *f, Lisp_Object spec, int face_id)
 {
   struct image *img;
   EMACS_UINT hash;
 
+  struct face *face = (face_id >= 0) ? FACE_FROM_ID (f, face_id)
+    : FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
+  unsigned long foreground = FACE_COLOR_TO_PIXEL (face->foreground, f);
+  unsigned long background = FACE_COLOR_TO_PIXEL (face->background, f);
+
   /* F must be a window-system frame, and SPEC must be a valid image
      specification.  */
   eassert (FRAME_WINDOW_P (f));
@@ -2324,7 +2346,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
 
   /* Look up SPEC in the hash table of the image cache.  */
   hash = sxhash (spec);
-  img = search_image_cache (f, spec, hash);
+  img = search_image_cache (f, spec, hash, foreground, background, true);
   if (img && img->load_failed_p)
     {
       free_image (f, img);
@@ -2337,9 +2359,9 @@ lookup_image (struct frame *f, Lisp_Object spec)
       block_input ();
       img = make_image (spec, hash);
       cache_image (f, img);
+      img->face_foreground = foreground;
+      img->face_background = background;
       img->load_failed_p = ! img->type->load (f, img);
-      img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
-      img->frame_background = FRAME_BACKGROUND_PIXEL (f);
 
       /* If we can't load the image, and we don't have a width and
         height, use some arbitrary width and height so that we can
@@ -2393,8 +2415,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
              if (!NILP (bg))
                {
                  img->background
-                   = image_alloc_image_color (f, img, bg,
-                                               FRAME_BACKGROUND_PIXEL (f));
+                   = image_alloc_image_color (f, img, bg, background);
                  img->background_valid = 1;
                }
            }
@@ -3667,8 +3688,8 @@ xbm_load_image (struct frame *f, struct image *img, char *contents, char *end)
                             &data, 0);
   if (rc)
     {
-      unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
-      unsigned long background = FRAME_BACKGROUND_PIXEL (f);
+      unsigned long foreground = img->face_foreground;
+      unsigned long background = img->face_background;
       bool non_default_colors = 0;
       Lisp_Object value;
 
@@ -3764,8 +3785,8 @@ xbm_load (struct frame *f, struct image *img)
     {
       struct image_keyword fmt[XBM_LAST];
       Lisp_Object data;
-      unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
-      unsigned long background = FRAME_BACKGROUND_PIXEL (f);
+      unsigned long foreground = img->face_foreground;
+      unsigned long background = img->face_background;
       bool non_default_colors = 0;
       char *bits;
       bool parsed_p;
@@ -6125,8 +6146,8 @@ pbm_load (struct frame *f, struct image *img)
       unsigned char c = 0;
       int g;
       struct image_keyword fmt[PBM_LAST];
-      unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
-      unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
+      unsigned long fg = img->face_foreground;
+      unsigned long bg = img->face_background;
       /* Parse the image specification.  */
       memcpy (fmt, pbm_format, sizeof fmt);
       parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
@@ -9433,6 +9454,7 @@ enum svg_keyword_index
   SVG_ALGORITHM,
   SVG_HEURISTIC_MASK,
   SVG_MASK,
+  SVG_FOREGROUND,
   SVG_BACKGROUND,
   SVG_LAST
 };
@@ -9451,6 +9473,7 @@ static const struct image_keyword svg_format[SVG_LAST] =
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":foreground",      IMAGE_STRING_OR_NIL_VALUE,              0},
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
@@ -9715,6 +9738,8 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
   int height;
   const guint8 *pixels;
   int rowstride;
+  char *wrapped_contents = NULL;
+  ptrdiff_t wrapped_size;
 
 #if ! GLIB_CHECK_VERSION (2, 36, 0)
   /* g_type_init is a glib function that must be called prior to
@@ -9722,6 +9747,8 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
   g_type_init ();
 #endif
 
+  /* Parse the unmodified SVG data so we can get its initial size.  */
+
 #if LIBRSVG_CHECK_VERSION (2, 32, 0)
   GInputStream *input_stream
     = g_memory_input_stream_new_from_data (contents, size, NULL);
@@ -9750,6 +9777,105 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
   rsvg_handle_write (rsvg_handle, (unsigned char *) contents, size, &err);
   if (err) goto rsvg_error;
 
+  /* The parsing is complete, rsvg_handle is ready to be used, close
+     it for further writes.  */
+  rsvg_handle_close (rsvg_handle, &err);
+  if (err) goto rsvg_error;
+#endif
+
+  /* Get the image dimensions.  */
+  rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
+
+  /* We are now done with the unmodified data.  */
+  g_object_unref (rsvg_handle);
+
+  /* Calculate the final image size.  */
+  compute_image_size (dimension_data.width, dimension_data.height,
+                      img->spec, &width, &height);
+
+  /* Wrap the SVG data in another SVG.  This allows us to set the
+     width and height, as well as modify the foreground and background
+     colors.  */
+  {
+    Lisp_Object value;
+    unsigned long foreground = img->face_foreground;
+    unsigned long background = img->face_background;
+
+    Lisp_Object encoded_contents
+      = Fbase64_encode_string (make_unibyte_string (contents, size), Qt);
+
+    /* The wrapper sets the foreground color, width and height, and
+       viewBox must contain the dimensions of the original image.  It
+       also draws a rectangle over the whole space, set to the
+       background color, before including the original image.  This
+       acts to set the background color, instead of leaving it
+       transparent.  */
+    const char *wrapper =
+      "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
+      "xmlns:xi=\"http://www.w3.org/2001/XInclude\" "
+      "style=\"color: #%06X; fill: currentColor;\" "
+      "width=\"%d\" height=\"%d\" preserveAspectRatio=\"none\" "
+      "viewBox=\"0 0 %d %d\">"
+      "<rect width=\"100%%\" height=\"100%%\" fill=\"#%06X\"/>"
+      "<xi:include href=\"data:image/svg+xml;base64,%s\"></xi:include>"
+      "</svg>";
+
+    /* FIXME: I've added 64 in the hope it will cover the size of the
+       width and height strings and things.  */
+    int buffer_size = SBYTES (encoded_contents) + strlen (wrapper) + 64;
+
+    value = image_spec_value (img->spec, QCforeground, NULL);
+    if (!NILP (value))
+      foreground = image_alloc_image_color (f, img, value, img->face_foreground);
+    value = image_spec_value (img->spec, QCbackground, NULL);
+    if (!NILP (value))
+      {
+        background = image_alloc_image_color (f, img, value, img->face_background);
+        img->background = background;
+        img->background_valid = 1;
+      }
+
+    wrapped_contents = malloc (buffer_size);
+
+    if (!wrapped_contents
+        || buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper,
+                                    foreground & 0xFFFFFF, width, height,
+                                    dimension_data.width, dimension_data.height,
+                                    background & 0xFFFFFF, SSDATA (encoded_contents)))
+      goto rsvg_error;
+
+    wrapped_size = strlen (wrapped_contents);
+  }
+
+  /* Now we parse the wrapped version.  */
+
+#if LIBRSVG_CHECK_VERSION (2, 32, 0)
+  input_stream = g_memory_input_stream_new_from_data (wrapped_contents, wrapped_size, NULL);
+  base_file = filename ? g_file_new_for_path (filename) : NULL;
+  rsvg_handle = rsvg_handle_new_from_stream_sync (input_stream, base_file,
+                                                 RSVG_HANDLE_FLAGS_NONE,
+                                                 NULL, &err);
+  if (base_file)
+    g_object_unref (base_file);
+  g_object_unref (input_stream);
+
+  /* Check rsvg_handle too, to avoid librsvg 2.40.13 bug (Bug#36773#26).  */
+  if (!rsvg_handle || err) goto rsvg_error;
+#else
+  /* Make a handle to a new rsvg object.  */
+  rsvg_handle = rsvg_handle_new ();
+  eassume (rsvg_handle);
+
+  /* Set base_uri for properly handling referenced images (via 'href').
+     See rsvg bug 596114 - "image refs are relative to curdir, not .svg file"
+     <https://gitlab.gnome.org/GNOME/librsvg/issues/33>. */
+  if (filename)
+    rsvg_handle_set_base_uri (rsvg_handle, filename);
+
+  /* Parse the contents argument and fill in the rsvg_handle.  */
+  rsvg_handle_write (rsvg_handle, (unsigned char *) wrapped_contents, wrapped_size, &err);
+  if (err) goto rsvg_error;
+
   /* The parsing is complete, rsvg_handle is ready to used, close it
      for further writes.  */
   rsvg_handle_close (rsvg_handle, &err);
@@ -9768,6 +9894,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
   pixbuf = rsvg_handle_get_pixbuf (rsvg_handle);
   if (!pixbuf) goto rsvg_error;
   g_object_unref (rsvg_handle);
+  free (wrapped_contents);
 
   /* Extract some meta data from the svg handle.  */
   width     = gdk_pixbuf_get_width (pixbuf);
@@ -9792,25 +9919,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
 
     init_color_table ();
 
-    /* Handle alpha channel by combining the image with a background
-       color.  */
-    Emacs_Color background;
-    Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
-    if (!STRINGP (specified_bg)
-       || !FRAME_TERMINAL (f)->defined_color_hook (f,
-                                                    SSDATA (specified_bg),
-                                                    &background,
-                                                    false,
-                                                    false))
-      FRAME_TERMINAL (f)->query_frame_background_color (f, &background);
-
-    /* SVG pixmaps specify transparency in the last byte, so right
-       shift 8 bits to get rid of it, since emacs doesn't support
-       transparency.  */
-    background.red   >>= 8;
-    background.green >>= 8;
-    background.blue  >>= 8;
-
     /* This loop handles opacity values, since Emacs assumes
        non-transparent images.  Each pixel must be "flattened" by
        calculating the resulting color, given the transparency of the
@@ -9822,16 +9930,11 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
            int red     = *pixels++;
            int green   = *pixels++;
            int blue    = *pixels++;
-           int opacity = *pixels++;
 
-           red   = ((red * opacity)
-                    + (background.red * ((1 << 8) - opacity)));
-           green = ((green * opacity)
-                    + (background.green * ((1 << 8) - opacity)));
-           blue  = ((blue * opacity)
-                    + (background.blue * ((1 << 8) - opacity)));
+            /* Skip opacity.  */
+           pixels++;
 
-           PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, red, green, blue));
+           PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, red << 8, green << 8, blue << 8));
          }
 
        pixels += rowstride - 4 * width;
@@ -9861,6 +9964,8 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
  rsvg_error:
   if (rsvg_handle)
     g_object_unref (rsvg_handle);
+  if (wrapped_contents)
+    free (wrapped_contents);
   /* FIXME: Use error->message so the user knows what is the actual
      problem with the image.  */
   image_error ("Error parsing SVG image `%s'", img->spec);
@@ -10159,7 +10264,7 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0,
   ptrdiff_t id = -1;
 
   if (valid_image_p (spec))
-    id = lookup_image (SELECTED_FRAME (), spec);
+    id = lookup_image (SELECTED_FRAME (), spec, -1);
 
   debug_print (spec);
   return make_fixnum (id);
index b7e4cbd56541e40fd8b460640405baa605552a97..e313fc03f406862804cfa2d12ea3d53ca4cf43dc 100644 (file)
@@ -1092,7 +1092,7 @@ update_frame_tool_bar (struct frame *f)
           continue;
         }
 
-      img_id = lookup_image (f, image);
+      img_id = lookup_image (f, image, -1);
       img = IMAGE_FROM_ID (f, img_id);
       prepare_image_for_display (f, img);
 
index a1f7706ead23689d36a61cf51eafd45739ec36ab..34644dff39c51b1c2b4b04704360851bd9284c1f 100644 (file)
@@ -5771,7 +5771,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
       else
        {
          it->what = IT_IMAGE;
-         it->image_id = lookup_image (it->f, value);
+         it->image_id = lookup_image (it->f, value, it->face_id);
          it->position = start_pos;
          it->object = NILP (object) ? it->w->contents : object;
          it->method = GET_FROM_IMAGE;
@@ -22517,7 +22517,7 @@ push_prefix_prop (struct it *it, Lisp_Object prop)
   else if (IMAGEP (prop))
     {
       it->what = IT_IMAGE;
-      it->image_id = lookup_image (it->f, prop);
+      it->image_id = lookup_image (it->f, prop, it->face_id);
       it->method = GET_FROM_IMAGE;
     }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -27431,7 +27431,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
          if (FRAME_WINDOW_P (it->f)
              && valid_image_p (prop))
            {
-             ptrdiff_t id = lookup_image (it->f, prop);
+             ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
              struct image *img = IMAGE_FROM_ID (it->f, id);
 
              return OK_PIXELS (width_p ? img->width : img->height);
index 0ebd5c7a195b19ab0e5e3a3b7778bafd2f794f47..02607e636763bed566399d9fae0d37a646bfb9be 100644 (file)
   (let ((image "<svg height='30' width='30'>
                   <rect x='0' y='0' width='10' height='10'/>
                   <rect x='10' y='10' width='10' height='10'
-                        style='fill:none;stroke-width:1;stroke:#000'/>
-                  <line x1='10' y1='10' x2='20' y2='20' style='stroke:#000'/>
-                  <line x1='20' y1='10' x2='10' y2='20' style='stroke:#000'/>
+                        style='fill:none;stroke-width:1;stroke:currentColor'/>
+                  <line x1='10' y1='10' x2='20' y2='20' style='stroke:currentColor'/>
+                  <line x1='20' y1='10' x2='10' y2='20' style='stroke:currentColor'/>
                   <rect x='20' y='20' width='10' height='10'
-                        style='fill:none;stroke-width:1;stroke:#000'/>
+                        style='fill:none;stroke-width:1;stroke:currentColor'/>
                 </svg>")
         (top-left "<svg height='10' width='10'>
                      <rect x='0' y='0' width='10' height='10'/>
                    </svg>")
         (middle "<svg height='10' width='10'>
                    <rect x='0' y='0' width='10' height='10'
-                         style='fill:none;stroke-width:1;stroke:#000'/>
-                   <line x1='0' y1='0' x2='10' y2='10' style='stroke:#000'/>
-                   <line x1='10' y1='0' x2='0' y2='10' style='stroke:#000'/>
+                         style='fill:none;stroke-width:1;stroke:currentColor'/>
+                   <line x1='0' y1='0' x2='10' y2='10' style='stroke:currentColor'/>
+                   <line x1='10' y1='0' x2='0' y2='10' style='stroke:currentColor'/>
                  </svg>")
         (bottom-right "<svg height='10' width='10'>
                          <rect x='0' y='0' width='10' height='10'
-                               style='fill:none;stroke-width:1;stroke:#000'/>
+                               style='fill:none;stroke-width:1;stroke:currentColor'/>
                        </svg>"))
     (insert-header "Test Crop: cropping an image (only works with ImageMagick)")
     (insert-test "all params" top-left image '(:crop (10 10 0 0)))
 (defun test-scaling ()
   (let ((image "<svg height='10' width='10'>
                   <rect x='0' y='0' width='10' height='10'
-                        style='fill:none;stroke-width:1;stroke:#000'/>
-                  <line x1='0' y1='0' x2='10' y2='10' style='stroke:#000'/>
-                  <line x1='10' y1='0' x2='0' y2='10' style='stroke:#000'/>
+                        style='fill:none;stroke-width:1;stroke:currentColor'/>
+                  <line x1='0' y1='0' x2='10' y2='10' style='stroke:currentColor'/>
+                  <line x1='10' y1='0' x2='0' y2='10' style='stroke:currentColor'/>
                 </svg>")
         (large "<svg height='20' width='20'>
                   <rect x='0' y='0' width='20' height='20'
-                        style='fill:none;stroke-width:2;stroke:#000'/>
+                        style='fill:none;stroke-width:2;stroke:currentColor'/>
                   <line x1='0' y1='0' x2='20' y2='20'
-                        style='stroke-width:2;stroke:#000'/>
+                        style='stroke-width:2;stroke:currentColor'/>
                   <line x1='20' y1='0' x2='0' y2='20'
-                        style='stroke-width:2;stroke:#000'/>
+                        style='stroke-width:2;stroke:currentColor'/>
                 </svg>")
         (small "<svg height='5' width='5'>
                   <rect x='0' y='0' width='4' height='4'
-                        style='fill:none;stroke-width:1;stroke:#000'/>
-                  <line x1='0' y1='0' x2='4' y2='4' style='stroke:#000'/>
-                  <line x1='4' y1='0' x2='0' y2='4' style='stroke:#000'/>
+                        style='fill:none;stroke-width:1;stroke:currentColor'/>
+                  <line x1='0' y1='0' x2='4' y2='4' style='stroke:currentColor'/>
+                  <line x1='4' y1='0' x2='0' y2='4' style='stroke:currentColor'/>
                 </svg>"))
     (insert-header "Test Scaling: resize an image (pixelization may occur)")
     (insert-test "1x" image image '(:scale 1))
 (defun test-scaling-rotation ()
   (let ((image "<svg height='20' width='20'>
                   <rect x='0' y='0' width='20' height='20'
-                        style='fill:none;stroke-width:1;stroke:#000'/>
+                        style='fill:none;stroke-width:1;stroke:currentColor'/>
                   <rect x='0' y='0' width='10' height='10'
-                        style='fill:#000'/>
+                        style='fill:currentColor'/>
                 </svg>")
         (x2-90 "<svg height='40' width='40'>
                   <rect x='0' y='0' width='40' height='40'
-                        style='fill:none;stroke-width:1;stroke:#000'/>
+                        style='fill:none;stroke-width:1;stroke:currentColor'/>
                   <rect x='20' y='0' width='20' height='20'
-                        style='fill:#000'/>
+                        style='fill:currentColor'/>
                 </svg>")
         (x2--90 "<svg height='40' width='40'>
                    <rect x='0' y='0' width='40' height='40'
-                         style='fill:none;stroke-width:1;stroke:#000'/>
+                         style='fill:none;stroke-width:1;stroke:currentColor'/>
                    <rect x='0' y='20' width='20' height='20'
-                         style='fill:#000'/>
+                         style='fill:currentColor'/>
                  </svg>")
         (x0.5-180 "<svg height='10' width='10'>
                      <rect x='0' y='0' width='10' height='10'
-                           style='fill:none;stroke-width:1;stroke:#000'/>
+                           style='fill:none;stroke-width:1;stroke:currentColor'/>
                      <rect x='5' y='5' width='5' height='5'
-                           style='fill:#000'/>
+                           style='fill:currentColor'/>
                    </svg>"))
     (insert-header "Test Scaling and Rotation: resize and rotate an image (pixelization may occur)")
     (insert-test "1x, 0 degrees" image image '(:scale 1 :rotation 0))