[css-images] Negative implications of linear gradient color space choice in CSS

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[css-images] Negative implications of linear gradient color space choice in CSS

Mark Straver
Hello people,

After some discussion in the Mozilla bugzilla [1] system I gathered this was a
better place to bring this up, since it seems to be a spec bug, at least in
part as a result from prior discussion in bugzilla. [2]

The specification for color stops in gradients states:

"At each color stop position, the line is the color of the color stop. Between
two color stops, the line’s color is interpolated between the colors of the
two color stops, with the interpolation taking place in premultiplied RGBA space."

There's a problem with using premultiplied RGBA space since it only caters
specifically to transitioning from fully opaque to fully transparent (and
dodging the undesired effect that the 'transparent' keyword is a shorthand for
only "transparent black" of the full range of transparent colors available).
The problem is that, as far as I know, it's *impossible* in premultiplied RGBA
space to get a linear gradient transition in both color and opacity, since the
color is directly tied to the opacity of the color stop.

e.g. linear-gradient (to bottom, rgba(255,255,0,1), rgba(255,0,0,0)) will
completely ignore the color of the target stop because it has opacity 0. One
can argue that a fully transparent color has no color, but it also influences
partially transparent color stops.
If the opacity of the target stop was, say, 0.1, then you'd only get a
proportional amount of red in the gradient to the opacity value -- this is
*not* a linear interpolation between both colors that one would expect from
the CSS statement.

I suggest a spec adjustment to make the 'transparent' keyword a special case
instead of just a simple shorthand, and make gradients work in
un-premultiplied RGBA space to allow proper transparent gradients to be
constructed.
For example, the 'transparent' keyword could be handled as an inherent stop of
the adjacent color with opacity 0 (on either side), or 2 stops if transparent
is somewhere "in the middle" of a gradient definition with each stop having
the color of the adjacent stop in that direction. This would avoid the "black"
transition that would otherwise occur with a simple shorthand.

Thanks for listening,

  Mark.

refs:
[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1241717
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=591600



Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Simon Fraser-4
> On Jan 22, 2016, at 10:12 am, Mark Straver <[hidden email]> wrote:
>
> Hello people,
>
> After some discussion in the Mozilla bugzilla [1] system I gathered this was a
> better place to bring this up, since it seems to be a spec bug, at least in
> part as a result from prior discussion in bugzilla. [2]
>
> The specification for color stops in gradients states:
>
> "At each color stop position, the line is the color of the color stop. Between
> two color stops, the line’s color is interpolated between the colors of the
> two color stops, with the interpolation taking place in premultiplied RGBA space."
>
> There's a problem with using premultiplied RGBA space since it only caters
> specifically to transitioning from fully opaque to fully transparent (and
> dodging the undesired effect that the 'transparent' keyword is a shorthand for
> only "transparent black" of the full range of transparent colors available).
> The problem is that, as far as I know, it's *impossible* in premultiplied RGBA
> space to get a linear gradient transition in both color and opacity, since the
> color is directly tied to the opacity of the color stop.
>
> e.g. linear-gradient (to bottom, rgba(255,255,0,1), rgba(255,0,0,0)) will
> completely ignore the color of the target stop because it has opacity 0. One
> can argue that a fully transparent color has no color, but it also influences
> partially transparent color stops.
> If the opacity of the target stop was, say, 0.1, then you'd only get a
> proportional amount of red in the gradient to the opacity value -- this is
> *not* a linear interpolation between both colors that one would expect from
> the CSS statement.
>
> I suggest a spec adjustment to make the 'transparent' keyword a special case
> instead of just a simple shorthand, and make gradients work in
> un-premultiplied RGBA space to allow proper transparent gradients to be
> constructed.
> For example, the 'transparent' keyword could be handled as an inherent stop of
> the adjacent color with opacity 0 (on either side), or 2 stops if transparent
> is somewhere "in the middle" of a gradient definition with each stop having
> the color of the adjacent stop in that direction. This would avoid the "black"
> transition that would otherwise occur with a simple shorthand.

This has been discussed several times in the past; we all agree that interpolating in non-premultiplied colors
is better, but this is not supported by the graphics frameworks on some platforms (e.g. by CoreGraphics on Mac)
so the spec is not able to mandate it.

Simon


Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Mark Straver
On 23/01/2016 19:23, Simon Fraser wrote:
> This has been discussed several times in the past; we all agree that interpolating in non-premultiplied colors
> is better, but this is not supported by the graphics frameworks on some platforms (e.g. by CoreGraphics on Mac)
> so the spec is not able to mandate it.

I understand that some hardware accelerated frameworks on some platforms might
not support drawing gradients directly in RGBA space and therefore be forced
to choose the poorer alternative (giving a different visual result in some
situations) or use software rendering (which is *always* an accurate option),
but the current wording actually mandates that a method be used that doesn't
allow one to create proper linear gradients with transparency.

Even if you can't mandate non-premultiplied colors, shouldn't you use wording
that non-premultiplied SHOULD be used (where possible) instead of forcing a
lowest-common denominator if you all agree that it's better the other way? And
maybe get a driver behind the non-supporting frameworks to actually improve it
and start supporting accurate gradients?

I'm running into a very practical limitation here from a design point of view
that shouldn't have to be there (even on affected frameworks these gradients
can still be rendered properly if pre-composed, right?).

I'm not aware of what all was discussed previously, but I do think this should
be adjusted - the current spec falls short of providing the desired and
expected tools and there is no hard reason why this lack of support by some
frameworks would have to limit the spec. Special-casing the 'transparent'
keyword IMHO would take away the main point that I know of that made
premultiplied colors desirable (avoiding black transitions).
Sorry if I'm re-iterating previously stated points.

Exactly on which frameworks and platforms would this be a problem?
On those frameworks/platforms, would pre-composition/software rendering not be
an option as a workaround and if so, why?



Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Rik Cabanier-2
In reply to this post by Simon Fraser-4


On Sat, Jan 23, 2016 at 10:23 AM, Simon Fraser <[hidden email]> wrote:
> On Jan 22, 2016, at 10:12 am, Mark Straver <[hidden email]> wrote:
>
> Hello people,
>
> After some discussion in the Mozilla bugzilla [1] system I gathered this was a
> better place to bring this up, since it seems to be a spec bug, at least in
> part as a result from prior discussion in bugzilla. [2]
>
> The specification for color stops in gradients states:
>
> "At each color stop position, the line is the color of the color stop. Between
> two color stops, the line’s color is interpolated between the colors of the
> two color stops, with the interpolation taking place in premultiplied RGBA space."
>
> There's a problem with using premultiplied RGBA space since it only caters
> specifically to transitioning from fully opaque to fully transparent (and
> dodging the undesired effect that the 'transparent' keyword is a shorthand for
> only "transparent black" of the full range of transparent colors available).
> The problem is that, as far as I know, it's *impossible* in premultiplied RGBA
> space to get a linear gradient transition in both color and opacity, since the
> color is directly tied to the opacity of the color stop.
>
> e.g. linear-gradient (to bottom, rgba(255,255,0,1), rgba(255,0,0,0)) will
> completely ignore the color of the target stop because it has opacity 0. One
> can argue that a fully transparent color has no color, but it also influences
> partially transparent color stops.
> If the opacity of the target stop was, say, 0.1, then you'd only get a
> proportional amount of red in the gradient to the opacity value -- this is
> *not* a linear interpolation between both colors that one would expect from
> the CSS statement.
>
> I suggest a spec adjustment to make the 'transparent' keyword a special case
> instead of just a simple shorthand, and make gradients work in
> un-premultiplied RGBA space to allow proper transparent gradients to be
> constructed.
> For example, the 'transparent' keyword could be handled as an inherent stop of
> the adjacent color with opacity 0 (on either side), or 2 stops if transparent
> is somewhere "in the middle" of a gradient definition with each stop having
> the color of the adjacent stop in that direction. This would avoid the "black"
> transition that would otherwise occur with a simple shorthand.

This has been discussed several times in the past; we all agree that interpolating in non-premultiplied colors
is better, but this is not supported by the graphics frameworks on some platforms (e.g. by CoreGraphics on Mac)
so the spec is not able to mandate it.

You have it reversed. The graphics frameworks in the browsers all interpolate in non-premultiplied data. I had to add emulation code to all the browsers to make this happen.

Like Mark, I proposed to treat transparent special but it fell on deaf ears [1]. I remember Tab and dbaron especially being opposed.
Unfortunately, now that Ion and I made all browsers compliant, it's likely too late to make this change

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Mark Straver
On 24/01/2016 06:37, Rik Cabanier wrote:
> The graphics frameworks in the browsers all interpolate in non-premultiplied
data. I had to add emulation code to all the browsers to make this happen.

So there's even less of a reason then to not change this...
Sorry to hear that so much extra work has been put into something that could
have been solved with the proposed approach the first time.

> Like Mark, I proposed to treat transparent special but it fell on deaf ears
> [1]. I remember Tab and dbaron especially being opposed.
> Unfortunately, now that Ion and I made all browsers compliant, it's likely too
> late to make this change

I don't think it's ever too late to make an improvement to a spec that is
beneficial for all involved and has no negatives. This is done all the time on
other specs, so why not here?

I understand that this might impact certain websites that explicitly rely on
premultiplied colors, but the common case (fade to transparent) would not be
affected.
It would need 2 changes to the spec:
1. Change the definition of "transparent" as a keyword to not be a shorthand
for rgba(0,0,0,0) but rather a transparent version of the adjacent color
2. Change the color space to use to be non-premultiplied RGBA

For the record, I've looked at implementing this special case for
'transparent' in my Mozilla-derived browser and it was *very* simple to do. I
gather all implementations in browsers would use a list (e.g. array or linked
list) of stops; all it takes is changing the "transparent" stop from
"transparent black" to the adjacent color value (previous or next) with
opacity 0. If transparent is "in the middle" is the only time the list length
changes because it needs to have a new stop inserted. I'm sure that inserting
an element into an existing list is something all implementations can do :)




Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Rik Cabanier-2
FWIW
Here's the discussion we had on the subject during TPAC:
https://lists.w3.org/Archives/Public/www-style/2012Nov/0262.html under Transitions/solved. The minutes are unfortunately bad.
Note that dbaron's assumption that Firefox implemented them was incorrect at the time.

On Sun, Jan 24, 2016 at 5:22 AM, Mark Straver <[hidden email]> wrote:
On 24/01/2016 06:37, Rik Cabanier wrote:
> The graphics frameworks in the browsers all interpolate in non-premultiplied
data. I had to add emulation code to all the browsers to make this happen.

So there's even less of a reason then to not change this...
Sorry to hear that so much extra work has been put into something that could
have been solved with the proposed approach the first time.

> Like Mark, I proposed to treat transparent special but it fell on deaf ears
> [1]. I remember Tab and dbaron especially being opposed.
> Unfortunately, now that Ion and I made all browsers compliant, it's likely too
> late to make this change

I don't think it's ever too late to make an improvement to a spec that is
beneficial for all involved and has no negatives. This is done all the time on
other specs, so why not here?

I understand that this might impact certain websites that explicitly rely on
premultiplied colors, but the common case (fade to transparent) would not be
affected.
It would need 2 changes to the spec:
1. Change the definition of "transparent" as a keyword to not be a shorthand
for rgba(0,0,0,0) but rather a transparent version of the adjacent color
2. Change the color space to use to be non-premultiplied RGBA

For the record, I've looked at implementing this special case for
'transparent' in my Mozilla-derived browser and it was *very* simple to do. I
gather all implementations in browsers would use a list (e.g. array or linked
list) of stops; all it takes is changing the "transparent" stop from
"transparent black" to the adjacent color value (previous or next) with
opacity 0. If transparent is "in the middle" is the only time the list length
changes because it needs to have a new stop inserted. I'm sure that inserting
an element into an existing list is something all implementations can do :)

It's slightly more complicated.
You need to substitute transparent with 2 coincident stops of the previous *and* the next color.

Removing the premultiplied calculations is indeed easy: remove the hacky code that adds premultiplied simulation. 

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Simon Fraser-4
In reply to this post by Rik Cabanier-2

On Jan 23, 2016, at 9:37 pm, Rik Cabanier <[hidden email]> wrote:

On Sat, Jan 23, 2016 at 10:23 AM, Simon Fraser <[hidden email]> wrote:

This has been discussed several times in the past; we all agree that interpolating in non-premultiplied colors
is better, but this is not supported by the graphics frameworks on some platforms (e.g. by CoreGraphics on Mac)
so the spec is not able to mandate it.

You have it reversed. The graphics frameworks in the browsers all interpolate in non-premultiplied data. I had to add emulation code to all the browsers to make this happen.

Are you sure?

Gradients with a transparent endpoint in Safari look grayish near the end, because alpha premultiplication has caused loss most of the RGB information. We need to interpolate with non-premultpliied alpha to be able to interpolate the color components and the alpha independently.

Simon

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Rik Cabanier-2


On Sun, Jan 24, 2016 at 10:25 PM, Simon Fraser <[hidden email]> wrote:

On Jan 23, 2016, at 9:37 pm, Rik Cabanier <[hidden email]> wrote:

On Sat, Jan 23, 2016 at 10:23 AM, Simon Fraser <[hidden email]> wrote:

This has been discussed several times in the past; we all agree that interpolating in non-premultiplied colors
is better, but this is not supported by the graphics frameworks on some platforms (e.g. by CoreGraphics on Mac)
so the spec is not able to mandate it.

You have it reversed. The graphics frameworks in the browsers all interpolate in non-premultiplied data. I had to add emulation code to all the browsers to make this happen.

Are you sure?

Yes, I am sure. Although it looks like I forgot to add the emulation code to Safari
If you open this in Safari:  https://jsfiddle.net/2ff05z2y/ you will see that the gradient is not in premultiplied space.
 
Gradients with a transparent endpoint in Safari look grayish near the end, because alpha premultiplication has caused loss most of the RGB information. We need to interpolate with non-premultpliied alpha to be able to interpolate the color components and the alpha independently.

Yes, they are gray-ish because the interpolate with transparent black.

Transitions should interpolate alpha and color indepently (unless you mean straight opacity?) 
Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Mark Straver
In reply to this post by Rik Cabanier-2
On 25/01/2016 06:52, Rik Cabanier wrote:
> It's slightly more complicated.
> You need to substitute transparent with 2 coincident stops of the previous
> *and* the next color.

Isn't that what I just said?
See:
>> If transparent is "in the middle" is the only time the list length
>> changes because it needs to have a new stop inserted. I'm sure that inserting
>> an element into an existing list is something all implementations can do :)

In all other cases it suffices to just change the color component:
Transparent -> Color and Color -> transparent (the most common cases on the
web) have transparent on the edge of the gradient, and don't need a second stop.
(r,g,b,0)->(r,g,b,a) and (r,g,b,a)->(r,g,b,0), etc.

Only if you have Color1 -> transparent -> Color2, where Color1 and Color2 are
*different*, do you need 2 stops. If the colors are the same then you don't,
because the color component of transparent would be equal anyway. You could
even optimize it further by only comparing the RGB components for the case of
(r1,g1,b1,a1)->transparent->(r1,g1,b1,a2) since the alpha for either adjacent
color is irrelevant. Not that I think it would be a practical win in terms of
performance or what not.

Even so, inserting an extra entry into an existing list isn't hard, and that
would be more an implementation question than a spec question. Just do this
somewhere between the CSS parsing step and the actual sending it to the
rendering engine step, and you're all good.



Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Tab Atkins Jr.
In reply to this post by Simon Fraser-4
On Sat, Jan 23, 2016 at 10:23 AM, Simon Fraser <[hidden email]> wrote:

> On Jan 22, 2016, at 10:12 am, Mark Straver <[hidden email]> wrote:
>> I suggest a spec adjustment to make the 'transparent' keyword a special case
>> instead of just a simple shorthand, and make gradients work in
>> un-premultiplied RGBA space to allow proper transparent gradients to be
>> constructed.
>> For example, the 'transparent' keyword could be handled as an inherent stop of
>> the adjacent color with opacity 0 (on either side), or 2 stops if transparent
>> is somewhere "in the middle" of a gradient definition with each stop having
>> the color of the adjacent stop in that direction. This would avoid the "black"
>> transition that would otherwise occur with a simple shorthand.

This wouldn't be backwards-compatible - "transparent" currently
computes to rgba(0,0,0,0) and lots of code in the wild depends on that
(specifically, it depends on always getting an rgba() result out of
getComputedStyle()), and any change would break things.

Premultiplied just makes some paths easier than non-premultiplied (and
the reverse is true as well).  You can still approximate an
"independent" transition of color and opacity by manually arcing the
gradient through the color space; you only need 3-4 stops to get
something generally indistinguishable from an unpremultiplied
transition.

> This has been discussed several times in the past; we all agree that interpolating in non-premultiplied colors
> is better, but this is not supported by the graphics frameworks on some platforms (e.g. by CoreGraphics on Mac)
> so the spec is not able to mandate it.

Wait, what? No, the *exact opposite* is true.  I switched the spec
over to doing premultiplied *over some people's objections* because it
gave better results in the common case.  The vast majority of
gradients to/from transparent just want the premultiplied result (they
don't think of it that way, but they want the "yellow goes
transparent" behavior, rather than "yellow turns kinda grayish as it
goes transparent" behavior).

If we had had a way to specify opacity independently from the color in
gradients (and it was as natural as saying "transparent"), then we
possibly could have kept gradients in unpremultiplied space.  But that
didn't happen, so eh..

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Rik Cabanier-2


On Mon, Jan 25, 2016 at 9:56 AM, Tab Atkins Jr. <[hidden email]> wrote:
On Sat, Jan 23, 2016 at 10:23 AM, Simon Fraser <[hidden email]> wrote:
> On Jan 22, 2016, at 10:12 am, Mark Straver <[hidden email]> wrote:
>> I suggest a spec adjustment to make the 'transparent' keyword a special case
>> instead of just a simple shorthand, and make gradients work in
>> un-premultiplied RGBA space to allow proper transparent gradients to be
>> constructed.
>> For example, the 'transparent' keyword could be handled as an inherent stop of
>> the adjacent color with opacity 0 (on either side), or 2 stops if transparent
>> is somewhere "in the middle" of a gradient definition with each stop having
>> the color of the adjacent stop in that direction. This would avoid the "black"
>> transition that would otherwise occur with a simple shorthand.

This wouldn't be backwards-compatible - "transparent" currently
computes to rgba(0,0,0,0) and lots of code in the wild depends on that
(specifically, it depends on always getting an rgba() result out of
getComputedStyle()), and any change would break things.

This proposal wouldn't change how the computed value of transparent changes. This is an under-the-hood change in the rendering code.
Are you worried about the computed value of the 'transparent' keyword in the gradient? If so, that one doesn't resolve to an rgba color.
 
Premultiplied just makes some paths easier than non-premultiplied (and
the reverse is true as well).  You can still approximate an
"independent" transition of color and opacity by manually arcing the
gradient through the color space; you only need 3-4 stops to get
something generally indistinguishable from an unpremultiplied
transition.

That is not true. If you go from 0-100, you will need 9 stops to avoid seams with lighter colors. Moreover, I have no idea what the result will look like by emulating CSS on top of the emulating C++. It potentially could create a hundreds of stops under the hood.
 
> This has been discussed several times in the past; we all agree that interpolating in non-premultiplied colors
> is better, but this is not supported by the graphics frameworks on some platforms (e.g. by CoreGraphics on Mac)
> so the spec is not able to mandate it.

Wait, what? No, the *exact opposite* is true.  I switched the spec
over to doing premultiplied *over some people's objections* because it
gave better results in the common case.  The vast majority of
gradients to/from transparent just want the premultiplied result (they
don't think of it that way, but they want the "yellow goes
transparent" behavior, rather than "yellow turns kinda grayish as it
goes transparent" behavior).

If we had had a way to specify opacity independently from the color in
gradients (and it was as natural as saying "transparent"), then we
possibly could have kept gradients in unpremultiplied space.  But that
didn't happen, so eh..

~TJ


Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Tab Atkins Jr.
On Mon, Jan 25, 2016 at 10:53 AM, Rik Cabanier <[hidden email]> wrote:

> On Mon, Jan 25, 2016 at 9:56 AM, Tab Atkins Jr. <[hidden email]>
> wrote:
>> On Sat, Jan 23, 2016 at 10:23 AM, Simon Fraser <[hidden email]> wrote:
>> > On Jan 22, 2016, at 10:12 am, Mark Straver <[hidden email]> wrote:
>> >> I suggest a spec adjustment to make the 'transparent' keyword a special
>> >> case
>> >> instead of just a simple shorthand, and make gradients work in
>> >> un-premultiplied RGBA space to allow proper transparent gradients to be
>> >> constructed.
>> >> For example, the 'transparent' keyword could be handled as an inherent
>> >> stop of
>> >> the adjacent color with opacity 0 (on either side), or 2 stops if
>> >> transparent
>> >> is somewhere "in the middle" of a gradient definition with each stop
>> >> having
>> >> the color of the adjacent stop in that direction. This would avoid the
>> >> "black"
>> >> transition that would otherwise occur with a simple shorthand.
>>
>> This wouldn't be backwards-compatible - "transparent" currently
>> computes to rgba(0,0,0,0) and lots of code in the wild depends on that
>> (specifically, it depends on always getting an rgba() result out of
>> getComputedStyle()), and any change would break things.
>
> This proposal wouldn't change how the computed value of transparent changes.
> This is an under-the-hood change in the rendering code.

By the time rendering code sees the value, it's been computed.

> Are you worried about the computed value of the 'transparent' keyword in the
> gradient? If so, that one doesn't resolve to an rgba color.

Sure it does.  (Or it should be doing so, for consistency - colors
should be computed in computed values.)

>> Premultiplied just makes some paths easier than non-premultiplied (and
>> the reverse is true as well).  You can still approximate an
>>
>> "independent" transition of color and opacity by manually arcing the
>> gradient through the color space; you only need 3-4 stops to get
>> something generally indistinguishable from an unpremultiplied
>> transition.
>
> That is not true. If you go from 0-100, you will need 9 stops to avoid seams
> with lighter colors.

In my own testing in the past, I only needed a few stops.  You need
more if you're manually arcing a path *in fully opaque colors*, but
it's hard to see seams in the mostly-transparent sections.

> Moreover, I have no idea what the result will look like
> by emulating CSS on top of the emulating C++. It potentially could create a
> hundreds of stops under the hood.

That's possible.  What of it?

(The underlying discussion of "can we change the behavior of today's
gradients" is almost certainly no, regardless of what details we
quibble over.)

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Rik Cabanier-2


On Mon, Jan 25, 2016 at 10:58 AM, Tab Atkins Jr. <[hidden email]> wrote:
On Mon, Jan 25, 2016 at 10:53 AM, Rik Cabanier <[hidden email]> wrote:
> On Mon, Jan 25, 2016 at 9:56 AM, Tab Atkins Jr. <[hidden email]>
> wrote:
>> On Sat, Jan 23, 2016 at 10:23 AM, Simon Fraser <[hidden email]> wrote:
>> > On Jan 22, 2016, at 10:12 am, Mark Straver <[hidden email]> wrote:
>> >> I suggest a spec adjustment to make the 'transparent' keyword a special
>> >> case
>> >> instead of just a simple shorthand, and make gradients work in
>> >> un-premultiplied RGBA space to allow proper transparent gradients to be
>> >> constructed.
>> >> For example, the 'transparent' keyword could be handled as an inherent
>> >> stop of
>> >> the adjacent color with opacity 0 (on either side), or 2 stops if
>> >> transparent
>> >> is somewhere "in the middle" of a gradient definition with each stop
>> >> having
>> >> the color of the adjacent stop in that direction. This would avoid the
>> >> "black"
>> >> transition that would otherwise occur with a simple shorthand.
>>
>> This wouldn't be backwards-compatible - "transparent" currently
>> computes to rgba(0,0,0,0) and lots of code in the wild depends on that
>> (specifically, it depends on always getting an rgba() result out of
>> getComputedStyle()), and any change would break things.
>
> This proposal wouldn't change how the computed value of transparent changes.
> This is an under-the-hood change in the rendering code.

By the time rendering code sees the value, it's been computed.

> Are you worried about the computed value of the 'transparent' keyword in the
> gradient? If so, that one doesn't resolve to an rgba color.

Sure it does.  (Or it should be doing so, for consistency - colors
should be computed in computed values.)

It does not. I tried Edge, Safari 9, latest Chrome and Firefox.
 

>> Premultiplied just makes some paths easier than non-premultiplied (and
>> the reverse is true as well).  You can still approximate an
>>
>> "independent" transition of color and opacity by manually arcing the
>> gradient through the color space; you only need 3-4 stops to get
>> something generally indistinguishable from an unpremultiplied
>> transition.
>
> That is not true. If you go from 0-100, you will need 9 stops to avoid seams
> with lighter colors.

In my own testing in the past, I only needed a few stops.  You need
more if you're manually arcing a path *in fully opaque colors*, but
it's hard to see seams in the mostly-transparent sections.

For darker colors, maybe. The eye picks up even subtle stepping in light colors. 
 
> Moreover, I have no idea what the result will look like
> by emulating CSS on top of the emulating C++. It potentially could create a
> hundreds of stops under the hood.

That's possible.  What of it?

Just saying that this should be tested to make sure it doesn't look weird.
 
(The underlying discussion of "can we change the behavior of today's
gradients" is almost certainly no, regardless of what details we
quibble over.)

I was resigned to that because I thought all browsers were in agreement. With Safari being the exception and another advocate, my hopes are up again :-)

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Tab Atkins Jr.
On Mon, Jan 25, 2016 at 11:17 AM, Rik Cabanier <[hidden email]> wrote:

> On Mon, Jan 25, 2016 at 10:58 AM, Tab Atkins Jr. <[hidden email]>
> wrote:
>> On Mon, Jan 25, 2016 at 10:53 AM, Rik Cabanier <[hidden email]> wrote:
>> > Are you worried about the computed value of the 'transparent' keyword in
>> > the
>> > gradient? If so, that one doesn't resolve to an rgba color.
>>
>> Sure it does.  (Or it should be doing so, for consistency - colors
>> should be computed in computed values.)
>
> It does not. I tried Edge, Safari 9, latest Chrome and Firefox.

Then that's a bug, either in the specs or the implementations.  There
is absolutely no reason a color should serialize differently based on
whether it's bare or wrapped in a gradient function.

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Mark Straver
In reply to this post by Rik Cabanier-2
On 25/01/2016 20:17, Rik Cabanier wrote:
>     In my own testing in the past, I only needed a few stops.  You need
>     more if you're manually arcing a path *in fully opaque colors*, but
>     it's hard to see seams in the mostly-transparent sections.
>
> For darker colors, maybe. The eye picks up even subtle stepping in light colors.

I'd have to agree here. Unless you want to manually add a LOT of stops, it's
not going to look pretty -- and it'll never be perfect, either.
Anyone with a decent screen would certainly see problems with an "emulated"
gradient with stops like that. I can't even imagine how this is going to look
on the next generation of 4k screens where this would become even more prominent.

> Just saying that this should be tested to make sure it doesn't look weird.
>
>     (The underlying discussion of "can we change the behavior of today's
>     gradients" is almost certainly no, regardless of what details we
>     quibble over.)
> I was resigned to that because I thought all browsers were in agreement. With
> Safari being the exception and another advocate, my hopes are up again :-)

I think a picture says more than 1000 words here.
Let me demonstrate exactly what I mean and what would logically be expected
when you'd create gradients, designing transparent transitions/overlays.
This is a live example from a browser using the proposed solution and NOT
premultiplying, with the CSS gradient code listed above the results for clarity.

https://dl.dropboxusercontent.com/u/1466747/lwt-test/gradient-transparent-test.png

Look at the CSS, and look at the picture - aren't these exactly the results
you'd logically want when looking at the gradient definitions? A designer
doesn't care about the exact underlying calculations or the math involved; a
designer wants to get what they expect when they provide instructions for a
specific goal.

Call me a rebel, but no quibbling over details will want me to move away from
this result with a series of less accurate (and potentially ugly) workarounds
just to satisfy the (apparently less gfx-native) "must use premultiplied
colors" point. The problem is simple, the solution is simple. There's no
reason to be stubborn about it :P


Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Xidorn Quan
In reply to this post by Tab Atkins Jr.
On Tue, Jan 26, 2016 at 6:22 AM, Tab Atkins Jr. <[hidden email]> wrote:

> On Mon, Jan 25, 2016 at 11:17 AM, Rik Cabanier <[hidden email]> wrote:
>> On Mon, Jan 25, 2016 at 10:58 AM, Tab Atkins Jr. <[hidden email]>
>> wrote:
>>> On Mon, Jan 25, 2016 at 10:53 AM, Rik Cabanier <[hidden email]> wrote:
>>> > Are you worried about the computed value of the 'transparent' keyword in
>>> > the
>>> > gradient? If so, that one doesn't resolve to an rgba color.
>>>
>>> Sure it does.  (Or it should be doing so, for consistency - colors
>>> should be computed in computed values.)
>>
>> It does not. I tried Edge, Safari 9, latest Chrome and Firefox.
>
> Then that's a bug, either in the specs or the implementations.  There
> is absolutely no reason a color should serialize differently based on
> whether it's bare or wrapped in a gradient function.

Given all impls current agree with the same behavior here, I guess we
can probably make 'transparent' a keyword value in gradient function
to simulate premultiplied effect, and revert the general cases to
non-premultiplied...

- Xidorn

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Tab Atkins Jr.
On Mon, Jan 25, 2016 at 3:29 PM, Xidorn Quan <[hidden email]> wrote:

> On Tue, Jan 26, 2016 at 6:22 AM, Tab Atkins Jr. <[hidden email]> wrote:
>> On Mon, Jan 25, 2016 at 11:17 AM, Rik Cabanier <[hidden email]> wrote:
>>> On Mon, Jan 25, 2016 at 10:58 AM, Tab Atkins Jr. <[hidden email]>
>>> wrote:
>>>> On Mon, Jan 25, 2016 at 10:53 AM, Rik Cabanier <[hidden email]> wrote:
>>>> > Are you worried about the computed value of the 'transparent' keyword in
>>>> > the
>>>> > gradient? If so, that one doesn't resolve to an rgba color.
>>>>
>>>> Sure it does.  (Or it should be doing so, for consistency - colors
>>>> should be computed in computed values.)
>>>
>>> It does not. I tried Edge, Safari 9, latest Chrome and Firefox.
>>
>> Then that's a bug, either in the specs or the implementations.  There
>> is absolutely no reason a color should serialize differently based on
>> whether it's bare or wrapped in a gradient function.
>
> Given all impls current agree with the same behavior here, I guess we
> can probably make 'transparent' a keyword value in gradient function
> to simulate premultiplied effect, and revert the general cases to
> non-premultiplied...

If and only if there's not a significant number of gradients out there
that currently write out transparent with rgba() syntax, or that use
near-transparent colors that'll significant change behavior here.

And we (Blink) must store the input string somewhere so we can output
it back literally, because I *know* that we parse that into an
#AARRGGBB 4-byte int and operate on it like that.  So it doesn't
matter whether you type "transparent" or "rgba(0,0,0,0)", you get
0x00000000 either way.

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Xidorn Quan
On Tue, Jan 26, 2016 at 10:48 AM, Tab Atkins Jr. <[hidden email]> wrote:

> On Mon, Jan 25, 2016 at 3:29 PM, Xidorn Quan <[hidden email]> wrote:
>> On Tue, Jan 26, 2016 at 6:22 AM, Tab Atkins Jr. <[hidden email]> wrote:
>>> On Mon, Jan 25, 2016 at 11:17 AM, Rik Cabanier <[hidden email]> wrote:
>>>> On Mon, Jan 25, 2016 at 10:58 AM, Tab Atkins Jr. <[hidden email]>
>>>> wrote:
>>>>> On Mon, Jan 25, 2016 at 10:53 AM, Rik Cabanier <[hidden email]> wrote:
>>>>> > Are you worried about the computed value of the 'transparent' keyword in
>>>>> > the
>>>>> > gradient? If so, that one doesn't resolve to an rgba color.
>>>>>
>>>>> Sure it does.  (Or it should be doing so, for consistency - colors
>>>>> should be computed in computed values.)
>>>>
>>>> It does not. I tried Edge, Safari 9, latest Chrome and Firefox.
>>>
>>> Then that's a bug, either in the specs or the implementations.  There
>>> is absolutely no reason a color should serialize differently based on
>>> whether it's bare or wrapped in a gradient function.
>>
>> Given all impls current agree with the same behavior here, I guess we
>> can probably make 'transparent' a keyword value in gradient function
>> to simulate premultiplied effect, and revert the general cases to
>> non-premultiplied...
>
> If and only if there's not a significant number of gradients out there
> that currently write out transparent with rgba() syntax, or that use
> near-transparent colors that'll significant change behavior here.

Yeah, sure. This needs to be proven first before any spec change on this.

> And we (Blink) must store the input string somewhere so we can output
> it back literally, because I *know* that we parse that into an
> #AARRGGBB 4-byte int and operate on it like that.  So it doesn't
> matter whether you type "transparent" or "rgba(0,0,0,0)", you get
> 0x00000000 either way.

It seems Gecko does so as well. But we already have an additional bit
for interpolation hint, so I guess we are not very concerned about
adding another bit for transparent keyword if the spec changes that
way.

- Xidorn

Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Rik Cabanier-2
In reply to this post by Tab Atkins Jr.


On Mon, Jan 25, 2016 at 3:48 PM, Tab Atkins Jr. <[hidden email]> wrote:
On Mon, Jan 25, 2016 at 3:29 PM, Xidorn Quan <[hidden email]> wrote:
> On Tue, Jan 26, 2016 at 6:22 AM, Tab Atkins Jr. <[hidden email]> wrote:
>> On Mon, Jan 25, 2016 at 11:17 AM, Rik Cabanier <[hidden email]> wrote:
>>> On Mon, Jan 25, 2016 at 10:58 AM, Tab Atkins Jr. <[hidden email]>
>>> wrote:
>>>> On Mon, Jan 25, 2016 at 10:53 AM, Rik Cabanier <[hidden email]> wrote:
>>>> > Are you worried about the computed value of the 'transparent' keyword in
>>>> > the
>>>> > gradient? If so, that one doesn't resolve to an rgba color.
>>>>
>>>> Sure it does.  (Or it should be doing so, for consistency - colors
>>>> should be computed in computed values.)
>>>
>>> It does not. I tried Edge, Safari 9, latest Chrome and Firefox.
>>
>> Then that's a bug, either in the specs or the implementations.  There
>> is absolutely no reason a color should serialize differently based on
>> whether it's bare or wrapped in a gradient function.
>
> Given all impls current agree with the same behavior here, I guess we
> can probably make 'transparent' a keyword value in gradient function
> to simulate premultiplied effect, and revert the general cases to
> non-premultiplied...

If and only if there's not a significant number of gradients out there
that currently write out transparent with rgba() syntax, or that use
near-transparent colors that'll significant change behavior here.

Given that a major browser has a different implementation and no bug reports, that number is likely small.
Also, when we made the change in the other browsers, there were no user reported bugs that we closed.
 
And we (Blink) must store the input string somewhere so we can output
it back literally, because I *know* that we parse that into an
#AARRGGBB 4-byte int and operate on it like that.  So it doesn't
matter whether you type "transparent" or "rgba(0,0,0,0)", you get
0x00000000 either way.

It looks like Safari, Edge and Chrome return the original CSS input string.
Firefox resolves color names to their rgba equivalents, but not 'transparent'
 
Reply | Threaded
Open this post in threaded view
|

Re: [css-images] Negative implications of linear gradient color space choice in CSS

Sebastian Zartner-3
As I stumbled over this issue again today and saw that there was no
final conclusion on this after rereading the whole thread, I'd like to
revive it.

On 26 January 2016 at 01:11, Rik Cabanier <[hidden email]> wrote:

>
> On Mon, Jan 25, 2016 at 3:48 PM, Tab Atkins Jr. <[hidden email]> wrote:
>>
>> On Mon, Jan 25, 2016 at 3:29 PM, Xidorn Quan <[hidden email]> wrote:
>> > On Tue, Jan 26, 2016 at 6:22 AM, Tab Atkins Jr. <[hidden email]> wrote:
>> >> On Mon, Jan 25, 2016 at 11:17 AM, Rik Cabanier <[hidden email]> wrote:
>> >>> On Mon, Jan 25, 2016 at 10:58 AM, Tab Atkins Jr. <[hidden email]>
>> >>> wrote:
>> >>>> On Mon, Jan 25, 2016 at 10:53 AM, Rik Cabanier <[hidden email]> wrote:
>> >>>> > Are you worried about the computed value of the 'transparent' keyword in
>> >>>> > the
>> >>>> > gradient? If so, that one doesn't resolve to an rgba color.
>> >>>>
>> >>>> Sure it does.  (Or it should be doing so, for consistency - colors
>> >>>> should be computed in computed values.)
>> >>>
>> >>> It does not. I tried Edge, Safari 9, latest Chrome and Firefox.
>> >>
>> >> Then that's a bug, either in the specs or the implementations.  There
>> >> is absolutely no reason a color should serialize differently based on
>> >> whether it's bare or wrapped in a gradient function.
>> >
>> > Given all impls current agree with the same behavior here, I guess we
>> > can probably make 'transparent' a keyword value in gradient function
>> > to simulate premultiplied effect, and revert the general cases to
>> > non-premultiplied...
>>
>> If and only if there's not a significant number of gradients out there
>> that currently write out transparent with rgba() syntax, or that use
>> near-transparent colors that'll significant change behavior here.
>
> Given that a major browser has a different implementation and no bug reports, that number is likely small.
> Also, when we made the change in the other browsers, there were no user reported bugs that we closed.

Could we get some statistics for the usage of rgba(0,0,0,0) instead of
'transparent' in gradients and color animations?
(Note that transitions between semi-transparent or opaque black and
rgba(0,0,0,0) need to be excluded.)

>> And we (Blink) must store the input string somewhere so we can output
>> it back literally, because I *know* that we parse that into an
>> #AARRGGBB 4-byte int and operate on it like that.  So it doesn't
>> matter whether you type "transparent" or "rgba(0,0,0,0)", you get
>> 0x00000000 either way.
>
>
> It looks like Safari, Edge and Chrome return the original CSS input string.
> Firefox resolves color names to their rgba equivalents, but not 'transparent'

On 25 January 2016 at 18:56, Tab Atkins Jr. <[hidden email]> wrote:

> On Sat, Jan 23, 2016 at 10:23 AM, Simon Fraser <[hidden email]> wrote:
>> On Jan 22, 2016, at 10:12 am, Mark Straver <[hidden email]> wrote:
>>> I suggest a spec adjustment to make the 'transparent' keyword a special case
>>> instead of just a simple shorthand, and make gradients work in
>>> un-premultiplied RGBA space to allow proper transparent gradients to be
>>> constructed.
>>> For example, the 'transparent' keyword could be handled as an inherent stop of
>>> the adjacent color with opacity 0 (on either side), or 2 stops if transparent
>>> is somewhere "in the middle" of a gradient definition with each stop having
>>> the color of the adjacent stop in that direction. This would avoid the "black"
>>> transition that would otherwise occur with a simple shorthand.
>
> This wouldn't be backwards-compatible - "transparent" currently
> computes to rgba(0,0,0,0) and lots of code in the wild depends on that
> (specifically, it depends on always getting an rgba() result out of
> getComputedStyle()), and any change would break things.

Given Rik's observations, this claim is incorrect, at least for gradients.

FWIW I agree with Mark and Rik that 'transparent' should be special
treated to mean transparent for the previous and next color instead of
transparent black.
So linear-gradient(red,transparent,blue) results in four color stops
rgba(255,0,0,1) @ 0% -> rgba(255,0,0,0) @ 50% -> rgba(0,0,255,0) @ 50%
-> rgba(0,0,255,1) @ 100%.

Also, I believe this topic is something that's worth to be discussed
in a CSSWG conf call or F2F, so we can get a proper resolution for it.

Sebastian

12