From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Alan Third Newsgroups: gmane.emacs.bugs Subject: bug#40845: SVG rendering issues Date: Sat, 22 Aug 2020 18:15:15 +0200 (CEST) Message-ID: <20200822161510.GB89421@breton.holly.idiocy.org> References: <20200425174651.GC82687@breton.holly.idiocy.org> <20200426211741.GA93046@breton.holly.idiocy.org> <09a19c49-91cb-8024-8c34-53d846d98313@gmail.com> <20200503141348.GA4071@breton.holly.idiocy.org> <83r1w1ovc3.fsf@gnu.org> <20200509142727.GA42881@breton.holly.idiocy.org> <20200509195415.GA44624@breton.holly.idiocy.org> <835zcx314r.fsf@gnu.org> <20200515214047.GB55337@breton.holly.idiocy.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="HcAYCG3uE/tztfnV" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="11529"; mail-complaints-to="usenet@ciao.gmane.io" To: Eli Zaretskii , cpitclaudel@gmail.com, 40845@debbugs.gnu.org, pipcet@gmail.com Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Aug 22 18:16:10 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1k9WBe-0002r2-2j for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 22 Aug 2020 18:16:10 +0200 Original-Received: from localhost ([::1]:35120 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k9WBd-0001h4-5d for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 22 Aug 2020 12:16:09 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:51606) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k9WBV-0001gr-W1 for bug-gnu-emacs@gnu.org; Sat, 22 Aug 2020 12:16:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:39627) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1k9WBV-0001Vi-N6 for bug-gnu-emacs@gnu.org; Sat, 22 Aug 2020 12:16:01 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1k9WBV-0007sM-IL for bug-gnu-emacs@gnu.org; Sat, 22 Aug 2020 12:16:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Alan Third Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 22 Aug 2020 16:16:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 40845 X-GNU-PR-Package: emacs Original-Received: via spool by 40845-submit@debbugs.gnu.org id=B40845.159811293028615 (code B ref 40845); Sat, 22 Aug 2020 16:16:01 +0000 Original-Received: (at 40845) by debbugs.gnu.org; 22 Aug 2020 16:15:30 +0000 Original-Received: from localhost ([127.0.0.1]:51173 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1k9WAz-0007QV-0g for submit@debbugs.gnu.org; Sat, 22 Aug 2020 12:15:30 -0400 Original-Received: from mailout-l3b-97.contactoffice.com ([212.3.242.97]:46580) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1k9WAt-0007GG-SU for 40845@debbugs.gnu.org; Sat, 22 Aug 2020 12:15:27 -0400 Original-Received: from smtpauth2.co-bxl (smtpauth2.co-bxl [10.2.0.24]) by mailout-l3b-97.contactoffice.com (Postfix) with ESMTP id 45AABD49; Sat, 22 Aug 2020 18:15:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1598112918; s=20200222-6h9o; d=idiocy.org; i=alan@idiocy.org; h=Date:From:To:Subject:Message-ID:References:MIME-Version:Content-Type:In-Reply-To; l=25903; bh=+7OveJZvlvx7zc8UjNyggH6s8wfdXnrN2B8Q9smFpzI=; b=f1Cc23i7e+Fl84nXGmO7/coW2pqYZWzl9cLTlMFayLopuBgg0jJa8J/aa6FQy5vk e2f3whUnkIDGTsDH5PsUKfzC2naWpaS+iFaO4embBrDBAwCZchmN/pzbB/KkNvWBfKo Td7DXDwi9VkRiwP0qUvWNEqzpjLVUzC1yuW9KI691QNIneItj7dokL00HQ3phl7oU/Q Ja4Q601c9H0C83vYXoYm023yMGXucUHhWemxPTuAFxe68jazuE7sIkEmrmz4yW5bcDp 8EgzOJOzDtFkTKCak8RPpOJMgOkWHD5gLEg1t95lrBuA7t8bMm+gLZZQxRZRZKaVIKr jZngC2o/tQ== Original-Received: by smtp.mailfence.com with ESMTPA ; Sat, 22 Aug 2020 18:15:11 +0200 (CEST) Original-Received: by breton.holly.idiocy.org (Postfix, from userid 501) id 8656F2024C4150; Sat, 22 Aug 2020 17:15:10 +0100 (BST) Mail-Followup-To: Alan Third , Eli Zaretskii , cpitclaudel@gmail.com, 40845@debbugs.gnu.org, pipcet@gmail.com Content-Disposition: inline In-Reply-To: <20200515214047.GB55337@breton.holly.idiocy.org> X-ContactOffice-Account: com:241649512 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:185969 Archived-At: --HcAYCG3uE/tztfnV Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, May 15, 2020 at 11:40:53PM +0200, Alan Third wrote: > > Take as long as you need, I'm in no great hurry. I still need to work > out how to calculate whether I should be using the mouse face and > decide exactly how to handle flushing an image from the cache as > it's somewhat broken in that patch. I still don't know how to use the mouse face. I couldn't see any way to detect if it's in use when we first load the image in xdisp.c. Most likely I've missed something, but if not then I worry that the easiest fix may be to actually support transparency when we draw to the screen instead of generating background colours when we load the images. I suspect we do it the way we do because it would have been slow on older machines, but modern machines should be able to handle it quickly via XRender and friends. As for the cache I decided to just delete all images that match the image spec, no matter what colours they use. It seems to me to be the safest option, as we don't want users flushing an image from the cache to display an updated version, only for the old one to reappear when the face changes. -- Alan Third --HcAYCG3uE/tztfnV Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0001-Set-basic-SVG-attributes-bug-40845.patch" >From e3ef587f86e3fe0fba1de80c070d495e06148c1b Mon Sep 17 00:00:00 2001 From: Alan Third Date: Sun, 3 May 2020 17:09:31 +0100 Subject: [PATCH] Set basic SVG attributes (bug#40845) * 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. --- lisp/net/shr.el | 17 --- src/dispextern.h | 6 +- src/gtkutil.c | 2 +- src/image.c | 205 ++++++++++++++++++++------ src/nsmenu.m | 2 +- src/xdisp.c | 6 +- test/manual/image-transforms-tests.el | 50 +++---- 7 files changed, 189 insertions(+), 99 deletions(-) diff --git a/lisp/net/shr.el b/lisp/net/shr.el index ddd8112721..24595301b7 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -1209,25 +1209,8 @@ shr-parse-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 - " " - (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 diff --git a/src/dispextern.h b/src/dispextern.h index 311867a0c8..88bbb71fb9 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3056,9 +3056,9 @@ reset_mouse_highlight (Mouse_HLInfo *hlinfo) 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 @@ #define TRY_WINDOW_IGNORE_FONTS_CHANGE (1 << 1) 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 face_id); #if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_NS #define RGB_PIXEL_COLOR unsigned long diff --git a/src/gtkutil.c b/src/gtkutil.c index 1fe160acca..fafd94c0f7 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -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); diff --git a/src/image.c b/src/image.c index 123de54ba2..297278ec9a 100644 --- a/src/image.c +++ b/src/image.c @@ -1081,7 +1081,7 @@ DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0, 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 @@ DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0, 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 @@ DEFUN ("image-metadata", Fimage_metadata, Simage_metadata, 1, 2, 0, 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 @@ DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0, SVG_ALGORITHM, SVG_HEURISTIC_MASK, SVG_MASK, + SVG_FOREGROUND, SVG_BACKGROUND, SVG_LAST }; @@ -9451,6 +9473,7 @@ DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0, {":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 it's 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,107 @@ 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 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 = + "" + "" + "" + ""; + + /* 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" + . */ + 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 +9896,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 +9921,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 +9932,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 +9966,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 +10266,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); diff --git a/src/nsmenu.m b/src/nsmenu.m index b7e4cbd565..e313fc03f4 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1092,7 +1092,7 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (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); diff --git a/src/xdisp.c b/src/xdisp.c index ad03ac4605..764d5345f2 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5696,7 +5696,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; @@ -22434,7 +22434,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 */ @@ -27335,7 +27335,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); diff --git a/test/manual/image-transforms-tests.el b/test/manual/image-transforms-tests.el index 0ebd5c7a19..02607e6367 100644 --- a/test/manual/image-transforms-tests.el +++ b/test/manual/image-transforms-tests.el @@ -48,24 +48,24 @@ test-cropping (let ((image " - - + style='fill:none;stroke-width:1;stroke:currentColor'/> + + + style='fill:none;stroke-width:1;stroke:currentColor'/> ") (top-left " ") (middle " - - + style='fill:none;stroke-width:1;stroke:currentColor'/> + + ") (bottom-right " + style='fill:none;stroke-width:1;stroke:currentColor'/> ")) (insert-header "Test Crop: cropping an image (only works with ImageMagick)") (insert-test "all params" top-left image '(:crop (10 10 0 0))) @@ -77,23 +77,23 @@ test-cropping (defun test-scaling () (let ((image " - - + style='fill:none;stroke-width:1;stroke:currentColor'/> + + ") (large " + style='fill:none;stroke-width:2;stroke:currentColor'/> + style='stroke-width:2;stroke:currentColor'/> + style='stroke-width:2;stroke:currentColor'/> ") (small " - - + style='fill:none;stroke-width:1;stroke:currentColor'/> + + ")) (insert-header "Test Scaling: resize an image (pixelization may occur)") (insert-test "1x" image image '(:scale 1)) @@ -107,27 +107,27 @@ test-scaling (defun test-scaling-rotation () (let ((image " + style='fill:none;stroke-width:1;stroke:currentColor'/> + style='fill:currentColor'/> ") (x2-90 " + style='fill:none;stroke-width:1;stroke:currentColor'/> + style='fill:currentColor'/> ") (x2--90 " + style='fill:none;stroke-width:1;stroke:currentColor'/> + style='fill:currentColor'/> ") (x0.5-180 " + style='fill:none;stroke-width:1;stroke:currentColor'/> + style='fill:currentColor'/> ")) (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)) -- 2.26.1 --HcAYCG3uE/tztfnV--