W3C home > Mailing lists > Public > www-style@w3.org > September 2013

[CSSWG] Minutes Paris F2F 2013-09-11 Wed III: Transitioning Image Values

From: fantasai <fantasai.lists@inkedblade.net>
Date: Thu, 19 Sep 2013 01:26:08 -0700
Message-ID: <523AB520.1040603@inkedblade.net>
To: "www-style@w3.org" <www-style@w3.org>
CSS Image Values

   - RESOLVED: When transitioning from plain image A to foo(A),
               infer the foo() on the other side (using no-op arguments)
   - RESOLVED: Mark as open issue whether interpolating complex
               images with the same source (e.g. foo(A) to bar(A))
               uses recursive interpolation (building a stack of
               compatible functions, e.g. foo(bar(A))) or
               just uses cross-fade().
   - RESOLVED: Accept proposal to shift misordered gradient stop
               fixup rules to after missing position interpolation
               and transition interpolation in order to make
               transitions layout-independent.
   - RESOLVED: No magic length interpolation for angle transitions
               in linear-gradient().
   - RESOLVED: Cannot interpolate to/from gradients with keyword
               direction (unless same keyword)

====== Full minutes below ======

CSS Image Values

Interpolation of Function'd Images

   TabAtkins: Interpolation rules for images
   TabAtkins: Generic rule for interpolating between two generic images --
              using cross-fade
   TabAtkins: Special rules for between gradients, between cross-fades,
              between filters
   <astearns> we have the first two
   TabAtkins: Interesting part is when interpolating between a plain image
              and a filtered image, friendlier to authors to pretend url
              was set up with null filters
   fantasai: I think that's obviously the right thing to do
   <glazou> http://dev.w3.org/csswg/css-images/#interpolating-images
   TabAtkins: Similarly for cross-fade

   TabAtkins: For other images, want to have normal image to special image
              handle smoothly
   TabAtkins: Question is then between two specialized transition rules.
   TabAtkins: How do we want to handle this?
   TabAtkins: Thought maybe use first one, but that's not symmetric across
               reversed transitions
   fantasai: Might want to go through all the combinations, and figure out
             which one makes most sense on the outside
   TabAtkins: So every time we introduce a new type, have to figure out
              where it goes in the hierarchy?
   fantasai: Yeah
   TabAtkins: That sounds reasonable

   Lea: Should cross-fade be interpreted as doing interpolation?
   TabAtkins: Interesting question
   TabAtkins: I think before had idea of having an interpolate() function,
              representing the interpolation between two images
   Lea: Filtered gradient to filtered gradient?
   TabAtkins: That's another issue...
   Shane: Can you give a specific example?
   TabAtkins: Transitioning from a filtered image to a cross-faded image.
              Do you use filtered image rules or cross-fade image rules?
   TabAtkins: fantasai suggested doing whichever rules wins
   fantasai: You'd do both, nested
   TabAtkins: ...
   krit: Filter function, cross-fade
   krit: Just cross fade? How would you want to interpolate?
   TabAtkins: If filter wins, re-interpolate as filter(cross-fade(url)))
   TabAtkins: Interpolate image functions, do recursive interpolation.
   krit: ... have to specify start/end
   TabAtkins: I'm not certain it's worth complexity of doing function stacks
   TabAtkins: Interpolate outer arguments, inner arguments
   krit: I think that's too complex.

   fantasai: Alternately, say they're two incompatible image types and
             just cross-fade them
   fantasai: Either you create compatible stacks of functions, filling in
             with no-ops, and interpolate; or you give up and cross-fade.
   fantasai: Doing some kind of partial interpolation doesn't make sense.
   Tab draws on the board
     1) filter(a,blur(5px))
     2) filter(b,blur(10px))
     a. filter(crossfade(a,b), blur(5px-10px))
     b. crossfade(1, 2)
   ChrisL: a will definitely look better in some cases, if there are large
           changes in the blur for example
   fantasai: I think that's mainly true if the source images are the same.
             Cross-fade should be fine if they're different.
   krit: a. seems like more work
   sylvaing: Hard to pick one vs other, because design intent is not clear
   sylvaing: Different source images, likely you just wanted cross-fade
   TabAtkins: Hard to infer author intent
   TabAtkins: Have inside and outside, have to figure out which one author
              intends on outside
   Shane: ...
   TabAtkins: Filters interpolate if you have same sources, same filters

   Shane: Think b is better, because people will be less likely to use
   Shane: It's easy to expand b) later into full recursive interpolation
   TabAtkins: For spec, just saying that filter function and future functions
              like this define their constraints, and if you miss those,
              just fall back into cross-fade
   krit: If you have a filtered gradient level 1 with same number of stops,
         different colors, do a cross-fade?
   TabAtkins: yes

   ChrisL: Case of different images where you want smarter interpolation
           is where one image is derived from the other
   ChrisL: e.g. text where original is flat, next is pop-up
   fantasai: Even in that case, doing a nice job with the blur interpolation
             won't make up for the act that you're cross-fading the shadow
             effect or movement effect, which still looks wrong
   ChrisL: fair enough

   Lea: Is there any reason not to do the fancy interpolation, other than
        implementation cost?
   TabAtkins: Just implementation cost. But in this case the difficulty
              doesn't seem worth the benefit. Benefit is positive, for
             recursive interpolation, but the difference is subtle, so
              small difference.
   TabAtkins: As Shane argued, decent chance that we can change it later
   TabAtkins: Unlikely to to break anything, likely to just make things
   plinss: Probably someone will depend on it anyway
   plinss: Is there a way to opt into different behavior?
   TabAtkins: Maybe?
   TabAtkins: Think we should just opt everyone in
   TabAtkins: But could do a flag on transition property or something

   krit: If we don't have consensus, should at least say that there are
         two options that we're considering
   fantasai: Seems fair to put both in the spec and ask for feedback

   Shane: Propos when you have two values that don't match, 50% switch
   Shane: If you want cross-fade, explicitly ask for it
   Shane: Makes it very unlikely that people will depend on it
   TabAtkins: We make things ugly when we don't want people to depend on it
   Shane: We want people to use this for matching values
   TabAtkins: Want people to be able to interpolate from plain image to
              filtered image
   fantasai: That's uncontroversial, I think. Case we're discussing is
             when both are complex images
   RESOLVED: transitioning from plain image A to foo(A), infer the foo()
             on the other side (using no-op arguments)

   TabAtkins: Don't do recursive interpolation of images, just do fancy
              interpolation on the top level
   Trying to figure out what all the suggested options are...
     a) recursive interpolation -- build stack of compatible functions,
        and fancy-interpolate them
     b) cross-fade incompatible types
     c) flip at 50%
   [url() or plain image is considered compatible with all transformed
    types with same source]

   [discussion of what same source means]
   TabAtkins: For gradients, would have to be exact same arguments
   TabAtkins: same function, same arguments

   Lea: Difference between cross-fade and fancy interpolation is not really
        that small
   Lea: e.g. interpolate between filtered gradients, where color stops are
        in different places (one side bias vs. other side bias)
   leaverou: If interpolate the gradient, will see the color stop shift
             and change
   leaverou: Very different from a cross-fade effect

   sylvaing: Is there a big perf cost for doing fancy interpolation, e.g.
             on phones?
   sylvaing: e.g. might need to use cross-fade always on the phone
   krit: of course
   sylvaing: recursive effect could be too expensive, esp on some devices
   sylvaing: So might not work on some devices
   leaverou: That's why I asked wrt implementation complexity. Perf is a
             different reason
   ChrisL: If you have a switch, can have a different style sheet on mobile
   sylvaing: And if author really wants recursive effect, can ask for it
   TabAtkins: OK, I'll leave this as an open issue
   RESOLVED: Mark this as an open issue in the draft
   <dbaron> I think it's worth actually researching likely performance costs.

Misordered Gradient Stops

   Topic: fixup rules for misordered gradient stops
   TabAtkins writes
   linear-gradient(white 100px, red 50px, blue, green 200px)
   TabAtkins: If you interpolate before fixup, blue gets 125
   TabAtkins: If you do fixup first, then interpolation, blue lands at 150
   TabAtkins: This is a minor issue in most cases, but if red's position
              is a percentage, then it depends on size of the image
   TabAtkins: So we can't finish the linear-gradient and be able to do
              transition computations until after layout
   <leaverou> wouldn't this also be an issue when doing interpolation
              between linear-gradient(blue, green 15%, blue) and
              linear-gradient(blue, green 15px, blue)? Isn't layout info
              needed here too?

   TabAtkins: Right now is fixup first, then position interpolation, then
              transition interpolation
   TabAtkins: Propose to position interpolation, transition interpolation,
              then fixup
   TabAtkins: Only affects when you have a misordered stop adjacent to an
              interpolated stop
   TabAtkins: Fairly uncommon case.
   TabAtkins: So I think this is a change that we can make
   TabAtkins: Think we refused to make the change earlier because we were
              fatigued and wanted the spec to just stop changing. But
              should make this change.
   krit: I implemented what Tab suggested, so we can see an example
   fantasai: What you say makes sense to me, and i agree with you that
             it's unlikely to break a significant number of changes, so
             I'm comfortable saying we should go through with the change.
   krit: I'm ok with the change too
   krit: got other issues, tho
   (not related to this)
   Leif: I feel ok with it at this point.
   RESOLVED: Proposal accepted

   [Bert asks for clarification]
   krit: Spec says repeating gradients repeat until infinity
   krit: I don't think that you can do that without information the
         gradient length
   Tab writes:
   TabAtkins: When transitioning between the two, repeat out to infinity
   dbaron: just need least-common-multiple of the length

   krit: you need to know position of the next color stop, doing interpolation
   krit: say yellow is -20px and black is at -10%
   TabAtkins: black and yellow then share a color stop
   [Tab explains how this all works]
   TabAtkins: Shouldn't need to do layout for this, can do all static.
   TabAtkins: Requires a bit of logic, but can do it
   Closed this as not an issue. Might need a clarification/example in the
   spec, though.

Animating Around Corners

   Next topic - linear gradients at different angles
   Example: Animating linear gradient that turns through 90deg or so
            in a box 100px tall, 300px wide
   TabAtkins: would stretch gradient from 100px to 316.2px back down to 300px
   TabAtkins: Suggestion is to have a monotonic change in the gradient
              length through the animation
   krit: This requires layout info for interpolation, which we were just
         trying to avoid
   TabAtkins: This is true... not sure how to get around it

   krit: I don't think that's a great use case
   TabAtkins: I've seen it, e.g. using gradient to emulate a light source
   Shane: If you assume that the gradient is always inside a square box...
   TabAtkins: Doesn't help
   fantasai: If you're going for a light source effect, you don't want to
             change the length of the gradient from the middle anyway--
             want the gradient attached to the edge. So you're breaking
             the use case.
   Shane: If we just do the nasty inflection point thing, you can get
          around it by providing more keyframes or something
   TabAtkins: So drop issue, just keep doing direct argument interpolation
   fantasai: People can provide explicit length if they need that
   RESOLVED: No change

Animating Angle<->Keyword Gradients

   New issue - keywords cannot be matched to specific degrees
   linear-gradient(45deg, ...)
   linear-gradient(to top left, ...)
   TabAtkins: Depending how you do this, might need layout info to resolve
              top left
   TabAtkins: For square, it's 45deg. For rectangle could be 30deg
   TabAtkins: Anywhere from 0-90deg, can't figure out until later
   TabAtkins: Could still preserve "to top left" as interpolated value
   dbaron: Maybe it's not worth making the other change, if we have to
           depend on layout here anyway?
   krit: I would just say don't interpolate at all in this case
   TabAtkins: At computed value time, corner keywords must remain themselves
   fantasai: So problem is you have no representation of the partway
   dbaron: I don't see the point in trying to limit cases where we need
           layout info if we already need layout info for this
   Discussion of interpolating between any two values
   dbaron: Implementing that requires some kind of interpolate-gradient
           syntax, internally at least
   dbaron: I guess this is going to be hard to implement
   fantasai: could come up with some kind of syntax to represent partway
             between keywords, even if it's awkward, nobody is going to
             want to use it anyway
   fantasai: e.g. linear-gradient(to top 50% top left, ...) be halfway
             between to top and to top left

   Shane: I implemented this before we punted to level 4
   Shane: pretty much all of it, or almost all of it
   Shane: The need to resolve everything down to used value was enough
          reason not to push to main branch
   Shane: Threw out the implementation
   Shane: Because doesn't interpolate like everything else interpolates
   TabAtkins: Why so much harder than dealing with calc()?
   krit: Before had to have layout info for fixup, don't anymore with new
   dbaron: I think in our implementation it would be conceptually similar
           to calc(), except with gradient functions instead.
   dbaron: Except gradient functions are more complex, so would be more
           complex code
   dbaron: You have to propagate the thing like calc() all the way through
   discussion of applying calc to individual stops vs. gradient functions

   TabAtkins: Someday need to deal with height: auto issue...
   Shane: I'm with krit, don't think we should allow interpolation between
          different keywords at this time
   TabAtkins: Some of these cases would require an explicit opt-in, e.g.
              height: 0 to height: auto
   TabAtkins: If we have switch for that, then can opt-in to more complicated
              gradient interpolations

   Shane: One difference between CSS and SVG is conversion to used value
   ChrisL: SVG conversions between gradient/color
   <ChrisL> this reminds me of the situation in SVG where we started only
            allowing interpolation between exactly matching things
   <ChrisL> and then gradually added more and more cases in response to
            feedback so eventually we could interpolate pretty much anything

   TabAtkins: Ok, I'm alright with that (not animating here)
   TabAtkins: Should we convert keywords that can be converted to degrees?
   fantasai: No, because we might eventually want keyword to keyword
   TabAtkins: OK
   RESOLVED: Cannot interpolate to/from keyword (unless same keyword)
   TabAtkins: Probably same for radial-gradient, too. Ok

   leaverou: Why is it not allowed to interpolate with different number
             of color stops, when can always pad with redundant color stops
   TabAtkins: Don't know where to pad: beginning, end, etc.
   leaverou: Can always specify explicitly
   leaverou: I just thought that any way we pick would be better than
   dbaron: Hard to get gradient stops to move if don't understand how they
           align up
   TabAtkins: Hard to guess what author's intent was
   TabAtkins: That's it for gradients

<br duration=15m>
Received on Thursday, 19 September 2013 08:26:37 UTC

This archive was generated by hypermail 2.3.1 : Thursday, 19 September 2013 08:26:38 UTC