On Tue, 23 Nov 2010 23:09:40 +0100, Philip Taylor <excors+wha...@gmail.com> wrote:
On Tue, Nov 23, 2010 at 8:43 PM, Tab Atkins Jr. <jackalm...@gmail.com> wrote:
Right now, canvas gradients interpolate their colors in
non-premultiplied space; that is, the raw values of r, g, b, and a are
interpolated independently.  This has the unfortunate effect that
colors darken as they transition to transparent, as "transparent" is
defined as "rgba(0,0,0,0)", a transparent black.  Under this scheme,
the color halfway between "yellow" and "transparent" is
"rgba(127,127,0,.5)", a partially-transparent dark yellow, rather than
"rgba(255,255,0,.5)".*

If you define the gradient as interpolating from solid yellow to
transparent black, I'd expect that it *should* be semi-transparent
blackish-yellow in the middle.

If you want it to be pure yellow, don't use a keyword which is
explicitly specified as transparent black - define the gradient from
rgba(255,255,0,1) to rgba(255,255,0,0) instead. Then you'll get
rgba(255,255,0,0.5) in the middle.

The rest of the platform has switched to using premultiplied colors
for interpolation, because they react better in cases like this**.
CSS transitions and CSS gradients now explicitly use premultiplied
colors, and SVG ends up interpolating similarly (they don't quite have
the same problem - they track opacity separate from color, so
transitioning from "color:yellow;opacity:1" to
"color:yellow;opacity:0" gives you "color:yellow;opacity:.5" in the
middle, which is the moral equivalent of "rgba(255,255,0,.5)").

That sounds like SVG gradients *can't* be using premultiplied colours.
A transition from "color:yellow;opacity:1" to "color:black;opacity:0"
will have rgba(127,127,0,0.5) in the middle, and it's impossible to
get that if you are using premultiplied colours. You'd have to have
A=1 at the start and A=0 at the end, so (with premultiplied colour)
the end would be interpreted as rgba(0,0,0,0), so you'd get the same
as interpolating to "color:yellow;opacity:0" (i.e. rgba(255,255,0,0.5)
in the middle), which is not what SVG does.

http://www.w3.org/TR/SVGTiny12/painting.html#Gradients says explicitly
its behaviour is the non-premultiplied behaviour we currently get with
canvas. ("gradient from fully transparent red, via partly transparent
dark yellow, to fully opaque lime" - the RGB components of fully
transparent colours are preserved.)

Maybe CSS should have originally used the keyword "transparentblack"
instead of "transparent" (though the distinction didn't matter before
gradients existed) - changing the gradient algorithm solely to work
more intuitively when people happen to use that one particular
incorrectly-named keyword seems backwards, and a mistake in CSS.

(Perhaps CSS gradients could avoid this problem by overriding the
meaning of the "transparent" keyword, so that instead of rgba(0,0,0,0)
it means A=0 with the mean RGB of the adjacent colour stops. That
would let it work as people naturally expect when they use that
keyword, and they can use the rgba() syntax if they really want
transparent black or transparent yellow or transparent red etc.)

The people at Opera responsible for the graphics layer agree with Philip's point of view. They also pointed out we do support rgba() in SVG.


--
Anne van Kesteren
http://annevankesteren.nl/

Reply via email to