Subject: bug#36315: closed (Re: bug#36315: Incorrect SVG color)

From: [email-masked] (GNU bug Tracking System)
Date: Fri, 18 Dec 2020 18:05:02 +0000

Your bug report

#36315: 27.0.50; SVG transparency handling is inaccurate

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
36315: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=36315
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#36315: Incorrect SVG color
From: Alan Third <[email-masked]>
To: Qiantan Hong <[email-masked]>
Cc: "[email-masked]" <[email-masked]>
Date: Fri, 18 Dec 2020 18:04:45 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

On Fri, Dec 18, 2020 at 04:42:03PM +0000, Qiantan Hong wrote:
> I fixed my build and it behaves correctly on macOS
> now.
> 
> M-x emacs-version
> GNU Emacs 28.0.50 (build 1, x86_64-apple-darwin18.7.0, NS appkit-1671.60 Version 10.14.6 (Build 18G6032)) of 2020-12-18

Excellent! Thanks for letting us know.

> To make sure I understand it, did we start outsourcing color some point after 27.1?

We pass the foreground and background colours into librsvg, which
creates the bitmap image that's displayed, in a commit that's just a
few months old. It will appear in Emacs 28.

I don't expect the change to be included in Emacs 27 since it's a
fairly large change introducing a number of new features and any new
Emacs 27 releases will be primarily bug fixes.
-- 
Alan Third

Subject: 27.0.50; SVG transparency handling is inaccurate
From: Pip Cet <[email-masked]>
To: [email-masked]
Date: Thu, 20 Jun 2019 20:26:53 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

Evaluate the following in emacs -Q:

(require 'svg)

(defun make-image (color)
  (let ((svg (svg-create 100 100)))
    (svg-rectangle svg 0 0 100 100 :fill color)
    (svg-image svg)))

(set-frame-parameter (window-frame) 'background-color "black")

(insert (propertize " " 'display (make-image "#f00000")))

The expected result is a rectangle (on black background) of color
#f00000. The actual result is a rectangle of color #ef0000. For black
backgrounds, white is no longer representable.

This is related to bug #36304, but much easier to fix.

Patch attached.
From 7abe6404d3af04db2f5a503c1c873f80ab86f69e Mon Sep 17 00:00:00 2001
From: Pip Cet <[email-masked]>
Date: Thu, 20 Jun 2019 20:13:12 +0000
Subject: [PATCH] SVG: scale color values properly

* src/image.c (svg_load_image): scale color channel values to proper
range.
---
 src/image.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/src/image.c b/src/image.c
index 866323ba6e..6b6235a617 100644
--- a/src/image.c
+++ b/src/image.c
@@ -9658,17 +9658,20 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
       {
 	for (int x = 0; x < width; ++x)
 	  {
-	    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)));
+	    unsigned int red     = *pixels++;
+	    unsigned int green   = *pixels++;
+	    unsigned int blue    = *pixels++;
+	    unsigned int opacity = *pixels++;
+
+	    /* opacity and the color channel values are in the range {0..255},
+	     * but expected output values are in the range {0..65535}, so scale
+	     * by (256/255)^2. */
+#define MIX(a, b, opacity)						\
+	    (((((a) * opacity) + ((b) * (255 - opacity))) * 65535 + 32512) / 65025)
+	    red   = MIX (red, background.red, opacity);
+	    green = MIX (green, background.red, opacity);
+	    blue  = MIX (blue, background.red, opacity);
+#undef MIX
 
 	    PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, red, green, blue));
 	  }
-- 
2.20.1