Re: [css3-images] Order of color-stop fixup

On Thu, Aug 11, 2011 at 8:24 PM, Brian Manthos <brianman@microsoft.com>wrote:

>  How are you addressing these interpolation scenarios without knowing more
> about the box:****
>
> i. corner-to-corner linear gradients (aspect ratio impacts interpolation of
> the intermediate angles)****
>
> ii. cover/contain radial gradients (distance from corners/sides impacts
> interpolation of the radii)****
>
> ** **
>
> ** **
>
> I would expect a number of properties that are sensitive to box size
> wouldn’t interpolate properly (or at all) with the system you described.**
> **
>
> ** **
>
> Interpolating before render time makes sense, but interpolating before
> layout/sizing doesn’t make sense to me.  It just seems way too early in the
> pipeline.****
>
> ** **
>
> If we continue down this path, it suggests that any and all properties with
> interpolation impacted by box size or ratio need to be revised or declared
> incompatible with interpolation.  That seems like the wrong approach for CSS
> going forward.  Maybe I’m misunderstanding.
>

Interpolating container-sensitive properties is still possible, it just
takes more work. I outlined how to do it in my previous email, but here it
is again:
(1) store non-resolved start and end values as part of the interpolated
result (e.g. [cover 30%, contain 70%] is the result of a 30% interpolation
between a cover gradient and a contain gradient)
(2) resolve start and end values against current size of container
(3) interpolate resolved values

Notice that there's an interesting twist here: the container size used is
the current size, not the size at the start (for cover) and end (for
contain). Obviously with a static container there's no difference, but what
happens if there's a dynamic container?

Interestingly, even if you do interpolate the renderable data rather than
the non-resolved values, you find yourself having to (1) store a snapshot of
the renderable state at the start, in order to be able to interpolate from
it; and (2) either guess at the container size at the end (actual knowledge
is not possible in the presence of animations that can be initiated by user
actions) or use the current size anyway.

Thinking about the problem further, take this case:
radial-gradient(center, ellipse contain, red, blue)
to
radial-gradient(center, ellipse contain, white, black)

The central question in my mind is: should the intermediate values of the
gradient obey contain? If they should (and I would argue that this makes
more sense) then you can't interpolate render-time data and you must store
the initial values in the interpolated result, as otherwise something like
this will result in a gradient that only covers 66% of the box after 1
second:

.box {
  width: 100px;
  height: 100px;
  background: radial-gradient(center, ellipse contain, red, blue);
  -webkit-transition-property: width, height, background;
  -webkit-transition-duration: 1s, 1s, 2s;
}

.box:hover {
  width: 200px;
  height: 200px;
  background: -webkit-radial-gradient(center, ellipse contain, blue, black);
}


> Getting back to the original question…****
>
> ** **
>
> Example A****
>
> linear-gradient(black, red -200%, white, blue)****
>
> ** **
>
> A - ED 5.4 current [2,3]****
>
> linear-gradient(black 0%, red 0%, white 50%, blue 100%)****
>
> 50% red to white, then 50% white to blue****
>
> ** **
>
> A - ED 5.4 proposed [3,2]****
>
> linear-gradient(black 0%, red 0%, white 0%, blue 100%)****
>
> 100% white to blue****
>
> ** **
>
> ** **
>
> Example B****
>
> linear-gradient(black 100px, red 20%, white, blue)****
>
> ** **
>
> B, 200px box - ED 5.4 current [2,3]****
>
> linear-gradient(black 100px, red 20%, white, blue 100%)****
>
> linear-gradient(black 50%, red 20%, white, blue 100%)****
>
> linear-gradient(black 50%, red 50%, white, blue 100%)****
>
> linear-gradient(black 50%, red 50%, white 75%, blue 100%)****
>
> 50% black, then 25% red to white, then 25% white to blue****
>
> ** **
>
> B, 400px box - ED 5.4 current [2,3]****
>
> linear-gradient(black 100px, red 20%, white, blue 100%)****
>
> linear-gradient(black 25%, red 20%, white, blue 100%)****
>
> linear-gradient(black 25%, red 25%, white, blue 100%)****
>
> linear-gradient(black 25%, red 25%, white 62.5%, blue 100%)****
>
> 25% black, then 37.5% red to white, then 37.5% white to blue****
>
> ** **
>
> B, 200px box - ED 5.4 proposed [3,2]****
>
> linear-gradient(black 100px, red 20%, white, blue 100%)****
>
> linear-gradient(black 100px, red 20%, white 60%, blue 100%)****
>
> linear-gradient(black 50%, red 20%, white 60%, blue 100%)****
>
> linear-gradient(black 50%, red 50%, white 60%, blue 100%)****
>
> 50% black, then 10% red to white, then 40% white to blue****
>
> ** **
>
> B, 400px box - ED 5.4 proposed [3,2]****
>
> linear-gradient(black 100px, red 20%, white, blue 100%)****
>
> linear-gradient(black 100px, red 20%, white 60%, blue 100%)****
>
> linear-gradient(black 25%, red 20%, white 60%, blue 100%)****
>
> linear-gradient(black 25%, red 25%, white 60%, blue 100%)****
>
> 25% black, then 35% red to white, then 40% white to blue****
>
> ** **
>
> ** **
>
> While it might be because I’m used to the current behavior, looking at the
> examples above I prefer the existing behavior. Why?  Because the even
> distribution of unspecified stops is consistently respected.  With the [3,2]
> proposal, the “overlapping stop correction” (2) trumps the even distribution
> which (IMO) is undesirable.
>

I'm just going to note here that the specification specifically recommends
against mixing pixel and percent stops; and that placing a stop at -200%
after a stop at 0% is not exactly a standard use case. Additionally:

Example 1:
linear-gradient(red -100%, white, green, black, blue)

Example 2:
linear-gradient(black, red -100%, white, green, black, blue)

Example 1 ED 5.4 current:
linear-gradient(red -100%, white -50%, green 0%, black 50%, blue 100%)

Example 2 ED 5.4 current:
linear-gradient(black 0%, red 0%, white 25%, green 50%, black 75%, blue
100%)

Why has adding a black stop before my explicitly specified red stop caused
all of my evenly spaced stops to shuffle up?  I asked for them to be spaced
between -100% and 100%.

Cheers,
    -Shane


> **
>
> I need to think about it some more, but just from the above I’m hesitant to
> change the order.
>


> Also, Tab, I suspect rearranging (2) and (3) has other implications that
> would take me more time to work through.  I don’t know if those implications
> are blocking or not, but it isn’t a trivial change that’s easy to evaluate.
> ****
>
> ** **
>
> -Brian****
>
> ** **
>
> *From:* Shane Stephens [mailto:shans@google.com]
> *Sent:* Thursday, August 11, 2011 6:04 PM
> *To:* Tab Atkins Jr.
> *Cc:* Brian Manthos; www-style list
> *Subject:* Re: [css3-images] Order of color-stop fixup****
>
> ** **
>
> I'd like to swap the order of (2) and (3) because:****
>
> ** **
>
> * (3) can be done when the style is applied (i.e. you don't need to know
> the box dimensions in order to evenly distribute stops), but (2) can only be
> done at render time (percentage values resolve relative to the size of the
> container).****
>
> * webkit currently interpolates applied styles, not renderable styles (this
> also means our implementation can't make use of the size of the container
> while interpolating)****
>
> * it's difficult (not impossible, but difficult) to interpolate between an
> implicitly placed stop and an explicitly placed stop, so it's nice to be
> able to resolve implicitly placed stops before interpolating.****
>
> ** **
>
> For example, interpolating between:****
>
> ** **
>
> linear-gradient(red 20%, white 20px, blue, black 100%)****
>
> and****
>
> linear-gradient(red 0%, white 20%, blue 40%, black 100%)****
>
> ** **
>
> If we need to defer spacing until we've resolved where the white stop is,
> then in webkit we'd need to represent a 50% interpolation for the blue stop
> as something like [auto@50%, 40%@50%] - i.e. a deferred interpolation
> calculation of 50% between implicit placement and 40% placement. This then
> needs to resolve at render time based on the current size of the container
> and the location of the white and black stops (put blue halfway between
> white and black, then interpolate halfway between that and the 40% point).
> Of course if the container size is changing then it's not even the start
> location of the blue stop that you're interpolating from but instead where
> the start location would be if the container were the current size (it's
> difficult to know how much this matters. I'll build a demo).****
>
> ** **
>
> On the other hand, if we can space at apply time, then this turns into:***
> *
>
> linear-gradient(red 20% + 0px, white 20px, blue 50% + 10px, black 100%)***
> *
>
> and****
>
> linear-gradient(red 0%, white 20%, blue 40%, black 100%)****
>
> ** **
>
> and we can then interpolate the blue stop at 50% as [45% + 5px], which is
> simpler to calculate and represent. Of course, the white stop may well still
> be shifted at render time because it's occluded by the red stop, but I'd
> like that not to impact the position of the blue stop.****
>
> ** **
>
> Hope this explains things a bit.****
>
> ** **
>
> Cheers,****
>
>     -Shane****
>
> ** **
>
> On Thu, Aug 11, 2011 at 4:29 PM, Tab Atkins Jr. <jackalmage@gmail.com>
> wrote:****
>
> On Thu, Aug 11, 2011 at 4:22 PM, Brian Manthos <brianman@microsoft.com>
> wrote:
> > Two corrections:
> > (1) Drop the e in the name. ;)****
>
> !_!  I've misread your name this entire time somehow.****
>
>
>
> > (2) I brought up an example suggesting we might want to be more explicit
> for calc.  I think the current rules are fine.****
>
> Ah, I misunderstood the intent of your example.  (Brian had sent me an
> example where all of the color-stops were using calc() with lengths
> and percentages.)
>
> ~TJ****
>
> ** **
>

Received on Friday, 12 August 2011 04:18:32 UTC