Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-28 Thread Tab Atkins Jr.
On Fri, Nov 26, 2010 at 8:44 PM, Boris Zbarsky bzbar...@mit.edu wrote:
 On 11/26/10 11:39 PM, Simon Fraser wrote:

 But CSS gradients are already requiring interpolation in premutiplied
 space, right?

 I think you're thinking of CSS Transitions, which we decided should run in
 premultiplied.

 No.  http://dev.w3.org/csswg/css3-images/#color-stop-syntax currently says:

  Between two color-stops, the line's color is linearly interpolated
  between the colors of the two color-stops, with the interpolation
  taking place in premultiplied RGBA space.

 and there was related discussion on www-style, iirc.

Note, though, that that's a relatively recent change that I made based
on dbaron's feedback.  That said, in the thread where I made the
change, Simon expressed that he'd like Transitions and Gradients to
work the same way, and I read him as preferring premultiplied.

~TJ


Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-26 Thread Simon Fraser
On Nov 23, 2010, at 12:43 PM, Tab Atkins Jr. wrote:

  Implementors, does
 this sounds like a change you can get behind?  We already changed
 canvas shadows to match behavior with CSS shadows; this is a much
 smaller change for spec-equivalence.

This would be hard for WebKit, which relies on Core Graphics for gradients
on some platforms. CG doesn't allow us to interpolate in premultiplied space.

[Of course, some of the new radial gradient stuff is also not doable using
CG, so maybe we'll have to have a slower non-CG gradient code
path anyway].

Simon



Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-26 Thread Boris Zbarsky

On 11/26/10 4:09 PM, Simon Fraser wrote:

This would be hard for WebKit, which relies on Core Graphics for gradients
on some platforms. CG doesn't allow us to interpolate in premultiplied
space.


But CSS gradients are already requiring interpolation in premutiplied 
space, right?


-Boris


Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-26 Thread Simon Fraser
On Nov 26, 2010, at 6:38 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 11/26/10 4:09 PM, Simon Fraser wrote:
 This would be hard for WebKit, which relies on Core Graphics for gradients
 on some platforms. CG doesn't allow us to interpolate in premultiplied
 space.
 
 But CSS gradients are already requiring interpolation in premutiplied space, 
 right?

I think you're thinking of CSS Transitions, which we decided should run in 
premultiplied.

Simon


Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-26 Thread Boris Zbarsky

On 11/26/10 11:39 PM, Simon Fraser wrote:

But CSS gradients are already requiring interpolation in premutiplied space, 
right?


I think you're thinking of CSS Transitions, which we decided should run in 
premultiplied.


No.  http://dev.w3.org/csswg/css3-images/#color-stop-syntax currently says:

  Between two color-stops, the line's color is linearly interpolated
  between the colors of the two color-stops, with the interpolation
  taking place in premultiplied RGBA space.

and there was related discussion on www-style, iirc.

-Boris


Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-25 Thread Anne van Kesteren
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/


Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-25 Thread Boris Zbarsky

On 11/25/10 1:59 PM, Anne van Kesteren wrote:

 They also pointed out we do support rgba() in SVG.


The point is that the resulting behavior is not defined by the SVG spec. 
 You could blow up the user's computer when using an rgba() color in 
SVG, and that would be as spec-compliant as anything else...


-Boris



Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-23 Thread Philip Taylor
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.)

-- 
Philip Taylor
exc...@gmail.com


Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-23 Thread Jonas Sicking
On Tue, Nov 23, 2010 at 2:09 PM, 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.

For what it's worth, I suspect most people don't think of
transparent as transparent black, but rather as fully
see-through.

/ Jonas


Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-23 Thread Tab Atkins Jr.
On Tue, Nov 23, 2010 at 2:09 PM, 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 fact that transparent means transparent black is a technical
detail that is usually irrelevant.  A fully transparent color doesn't
really have a color at all.  I'm highly technical, involved in the
relevant specs, and understand the underlying math, and I *still* get
tripped up over the fact that transparent is black.


 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.

Luckily I didn't say that SVG used premultiplied colors.  ^_^  I said
they end up interpolating in a similar way, if you do the obvious
thing and just adjust the opacity.

When using CSS colors, the obvious thing is to use the transparent
keyword, which gives unsatisfactory behavior most of the time if you
transition in plain rgba space.


 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.

Possibly, but that can't be fixed now, and so as a result both
Transitions/Animations and Gradients use premultiplied colors, and
won't likely change (I know that Apple and Moz support using
premultiplied colors in transitions and gradients).  Making canvas
gradients match CSS seems like a better idea than the reverse at this
point, and seems more likely to have implementor support.

 (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.)

This is incompatible with both gradients and transitions (actually,
animations), because transparent can be simultaneously the endpoints
of two different color interpolations.

An animation or a gradient can go from a solid color to transparent to
a solid color again.  While it's theoretically possible in a
red-transparent-blue animation/gradient to have transparent mean
rgba(255,0,0,0) when going from red-transparent, and then mean
rgba(0,0,255,0) when going from transparent-blue, that's hacky and
weird.  Doing it in premultiplied space makes it all happen cleanly
and automatically.

~TJ


Re: [whatwg] Canvas gradients color interpolation - change to premultiplied?

2010-11-23 Thread L. David Baron
On Tuesday 2010-11-23 22:09 +, Philip Taylor 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.

Sure, you can solve that particular case.  However, if neither of
the endpoints is precisely transparent, and you're changing both
color and alpha components, you'll still get an ugly effect with the
current rules, and one that you can't work around.  (I experimented
with both methods when implementing CSS transitions of colors, and
went with premultiplied.
http://dbaron.org/css/test/2009/transitions/transitions-alpha makes
it look like WebKit has now switched to premultiplied.)

 That sounds like SVG gradients *can't* be using premultiplied colours.

Yes, because SVG doesn't have RGBA colors; it has RGB colors (in
stop-color) and a separate stop-opacity property/attribute.  So the
choice doesn't apply to SVG.

 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.

It's not only the 'transparent' keyword; it affects all cases of
gradients between colors with different alpha values and different
color values.  And in cases where one of the endpoint alphas is not
0, it's not possible to get the correct (premultiplied) result with
a gradient computed in nonpremultiplied space.

-David

-- 
L. David Baron http://dbaron.org/
Mozilla Corporation   http://www.mozilla.com/