Closed Bug 546052 Opened 11 years ago Closed 5 months ago

Implement parsing for cross-fade() from CSS Image Values and Replaced Content Module Level 4

Categories

(Core :: CSS Parsing and Computation, enhancement, P2)

enhancement

Tracking

()

RESOLVED FIXED
81 Branch
Tracking Status
firefox81 --- fixed

People

(Reporter: Dolske, Assigned: zekemedley)

References

(Depends on 2 open bugs, Blocks 3 open bugs, )

Details

Attachments

(1 file)

The CSS Transitions spec currently doesn't deal with images [transitions from url(img1.png) --> url(img2.png)]. It would be nice to be able to cross-fade when changing images, instead of having a sudden change.

For example, Firefox Personas simply set the background-image on a few chrome elements. When browsing available Personas, it would be very pleasant to have a soft cross-fade occur. In some cases one could do this manually, by stacking images and transitioning topmost's opacity, but that might be hard for Personas.

Other likely use-cases could be transitions between UI button states (eg, videocontrols play/pause), and things like slideshows. [The scope here could be widened to any CSS-control image (list-style-image, border-image, etc), but starting off with background-image would be most useful to me.]

One obvious tricky bit is when to start the transition, given that the image resource might need to be loaded. [Wait until onload? Or not? How to coordinate with other transitions?]
I know, this isn't W3C conform, but this would partially solve the problem with fading transitions of background-images, that doesn't have a sourceimage, but have been build with gradients, too.

They could be prerendered and then faded in. I know this does more (transition of whole pictures) and than again less than the W3C asks for (and therefore isn't totally conform), but gradients should be "interpolated via the positions and colors of each stop. They must have the same type (radial or linear) and same number of stops in order to be animated. " Except the possibility to animatedly "move" those in-between stops, it would at least somehow give the ability to transit gradients.

It should be considered to be implemented as a placeholder feature into the next version of gecko, until the real thing arrives. (I'm not aware of the current development of gecko concerning this matter. Please feel free to post a link.)

The alternative would be to swallow the bitter pill, that every step (25 in 1s) of a background-image transition has to be rendered the hard way and to finally get over with it, as it seems to be time.

Ahh, I went a little bit offtopic.
Back to the interpolation of two pictures. Even in later steps, when the W3C rules have been applied, I see no reasons, why two pictures in a changing background-image property shouldn't be interpolated. It wouldn't be the first time the W3C adapted new features.
There are multiple options here, once gradients get involved.  See:
http://lists.w3.org/Archives/Public/public-fx/2010AprJun/0009.html
http://lists.w3.org/Archives/Public/public-fx/2010AprJun/0013.html

We might need to think about ways for an author to choose between different transform mechanisms.
(In reply to comment #2)
> We might need to think about ways for an author to choose between different
> transform mechanisms.

Hmm. Let them decide, if the transition-effect between two images should be a simple crossfade, blur, mosaic or swapping wave-effect. The simplest way to do that, I can come up with,  would be to abuse the transition-timing-function and define "exotic" values, like blur-ease, mosaic-linear, wave-bezier(w,x,y,z) (with ease, linear, cubic-bezier(...) being the values for crossfading). Those should only work on the background-image property and fall back onto their equivalent standard values or throw an exception, if used on other properties.

Another problem is, that background-images may consist of more than one level.

Example:
.box {
  background-image: url("softkittyalpha.png"), /*level 0, rendered last*/
                    url("ocean.png"), /*level 1*/
                    -moz-linear-gradient(rgb(100,100,255),blue 50%);
  background-position: center, center, 0;
  background-repeat: none;
}

.box:hover {
  background-image: url("demonalpha.png"),
                    url("hell.png"),
                    -moz-linear-gradient(yellow,red 50%);
}

I propose abusing the transition-property-function by creating special values, that are no properties, but "link" to the levels of the background-image property. (background-image(0) background-image(1) background-image(2))

A transition-function property might look as the following:

-moz-transition: background(0) 1.25s blur-linear 1s,
                 background(1)  .25s wave-linear .87s;

This at least does look conform.

Other effects like changing effects midways in a transition like proposed in http://lists.w3.org/Archives/Public/public-fx/2010AprJun/0007.html, do sound awesome, but are so advanced, I have no hard feelings, if they are postponed until css4.
Of course it's "background-repeat: no-repeat;" and "-moz-transition: background-image(0) 1.25s...,background-image(1)..."

All those fancy effects, discussed in those e-mails, are fine, but before thinking about, what else could be done, that even looks more awesome, shouldn't the simpler approaches be implemented?
I propose the following plan. (As I haven't deeply acquainted myself with this matter, I don't know, when I propose illogical or unrealistic steps.)


Step 1:
Implementing a simple cross-fade between two background-images, each as a whole, if they have the same size. If they don't have the same size, no transition effect will be applied.
This would do justice to this bug here and would help people a great deal, that have to use this image transition opacity workaround http://css-tricks.com/fade-image-within-sprite/
At this point W3C's goals still aren't achieved, but webdesigners do have something to work with.

Step 2:
Breaking up the rendering of the effects into the background-images levels. For each kind of transition (picture-picture, gradient-gradient) one animation effect will be defined as standard. (At first cross-fading for all of them.) Giving the ability to choose between effects will be postponed until step 3.
Then these effects will be changed/updated. I.e. picture-picture cross-fading will gain the ability to handle different sizes picures, while gradient-gradient transitions will become more and more W3C conform.
The used transition-timing value should still apply to all transitions of the background-image property.
The goal of this step should be to let background-image transitions gain the ability to work, even if the starting and ending images have different sizes, and to fulfill all of the W3C requirements.

Step 3:
Extending the css syntax or the pseudo-functions to give the ability to choose between different effects for the images on the different background-image levels, like proposed in comment 3 for example. This step also include to choose different transition-timing values for each level.
The goal: to go beyond.
(In reply to comment #4)
> Step 1:
> Implementing a simple cross-fade between two background-images, each as a
> whole, if they have the same size. If they don't have the same size, no
> transition effect will be applied.

I don't see any reason to have such a same-size restriction.  Just cross-fade.

> At this point W3C's goals still aren't achieved, but webdesigners do have
> something to work with.

What goals of W3C are involved here?

> Step 2:
> Breaking up the rendering of the effects into the background-images levels. For
> each kind of transition (picture-picture, gradient-gradient) one animation
> effect will be defined as standard. (At first cross-fading for all of them.)
> Giving the ability to choose between effects will be postponed until step 3.

I don't see why this is any more work than step 1.
(In reply to comment #5)
> I don't see any reason to have such a same-size restriction.  Just cross-fade.

Step 1 is meant as a quickfix. I was under the impression, that different image sizes could cause trouble by creating a debate over, how to handle the transition. (Resizing, stretching, aso.) I wanted to avoid it. But I didn't think strait. Of course a simple cross-fade is sufficient. My bad. Step 2's improvement of picture-picture transition becomes obsolete, too.

> What goals of W3C are involved here?

Yet again my bad. Bad choice of words. I just wanted to say, that the specifications given by the W3C (concerning transitions of gradients)
still aren't met at that point. (I'm cutting my Women,World&Watermelons conquest joke, as it's lame.)
 
> I don't see why this is any more work than step 1.

Implementing step 1 should be easy, as it only involves rendering the before and after images of background-image and interpolate them.
Step 2 on the other hand includes the development of an animated transition effect for linear and radial gradients (smooth transitions of the stops, colors and resizing-handling; called (1) by you in http://lists.w3.org/Archives/Public/public-fx/2010AprJun/0009.html ), that is conform with the transition specs given by the W3C. It's more detailed work than step 1.
Maybe step 2 also involves optimizing the rendering too (if possible), as I only can think of the straight forward approach, that is: Compute all values for each layer of a background-image in transition, draw each layer on another, until an in-between image has been finished, draw that onto the screen and the whole procedure at least 25 times a second.
BTW: What really worries me, is the amount of computation steps needed in the  rendering process. Rendering 25 in-between pictures per second shouldn't be a big problem for 50px*30px buttons or two layer 800px*600px images. But what about five 600px*200px images with 4+ layers and tons of alphaeffect gradients, that might go of simultaneously? Well, I guess not creating monsters is the webdesigners responsibility.
Chrome nightly recently added support for cross-fading backgrounds, as demonstrated here: http://dabblet.com/gist/1931619
Summary: Support CSS transitions with background-image images (cross-fading) → [css4-images] Support CSS transitions with background-image images (cross-fade())
Depends on: 801844
This feature has been moved to css-image-3, and this spec is already CR. https://drafts.csswg.org/css-images-3/#cross-fade-function
See also bug 536540
Duplicate of this bug: 1305449
https://github.com/w3c/csswg-drafts/issues/1148 suggests to move this to css-image-4, as it's missing implementations.

Sebastian
Alias: cross-fade
Summary: [css4-images] Support CSS transitions with background-image images (cross-fade()) → Implement cross-fade() from CSS Image Values and Replaced Content Module Level 3
cross-fade is now supported in chrome/blink with the -webkit- prefix, and in Safari/iOS without prefix. Have added feature to MDN https://developer.mozilla.org/en-US/docs/Web/CSS/cross-fade
See Also: → 1540583
Blocks: 674232

Assigning to Zeke and updating title since this got moved to level 4 a while ago.

Assignee: nobody → zekemedley
Severity: normal → N/A
Status: NEW → ASSIGNED
Priority: -- → P2
Summary: Implement cross-fade() from CSS Image Values and Replaced Content Module Level 3 → Implement cross-fade() from CSS Image Values and Replaced Content Module Level 4

This is the first of what will likely be two patches for cross-fade's
implementation. Bug 546052 tracks it's complete implementation.

The cross-fade implementation in Safari and -webkit-cross-fade in Chromium currently implement a different syntax than the one that is specified by the CSSWG. You can read more about it on MDN here but in summary, it only allows for two images to be faded together and the percentages for the images are specified together at the end rather than with each image.

I'm of the opinion that we should go ahead and implement the newer syntax that is specified by the CSSWG. According to Can I Use and a couple of my own queries on httparchive's data this older syntax has very little usage. Additionally, the newer syntax is incompatible with the older implemented syntax so for the few webpages that do currently use cross-fade the status quo will persist as their cross-fade will continue to not work on Firefox.

If anyone has any input on that, I'd love to hear your thoughts. If not I'll carry on implementing the newer syntax only :)

Just so I don't forget to check the patch later.

Flags: needinfo?(emilio)
Flags: needinfo?(emilio)
Depends on: 1653703
Pushed by dluca@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/9e9c50bbb2f3
Add parsing for cross-fade from CSS Image Values and Replaced Content Module Level 4 r=emilio
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/24790 for changes under testing/web-platform/tests

Looks like this made us fail a build-time check of some sort:

---- size_of::test_size_of_computed_image stdout ----
[task 2020-07-28T23:07:00.661Z] 23:07:00 INFO - thread 'size_of::test_size_of_computed_image' panicked at 'Your changes have increased the stack size of computed::image::Image from 16 to 24. Please consider choosing a design which avoids this increase. If you feel that the increase is necessary, update the size in servo/ports/geckolib/tests/size_of.rs.', servo/ports/geckolib/tests/size_of.rs:69:1

https://treeherder.mozilla.org/logviewer.html#/jobs?job_id=311325559&repo=autoland&lineNumber=14411

I suspect a backout is incoming, and then you can sort out how best to deal with that ^ with emilio.

Flags: needinfo?(zekemedley)
Upstream PR merged by moz-wptsync-bot
Pushed by ccoroiu@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/eec8614e56fa
Add parsing for cross-fade from CSS Image Values and Replaced Content Module Level 4 r=emilio
Status: ASSIGNED → RESOLVED
Closed: 6 months ago
Resolution: --- → FIXED
Target Milestone: --- → 81 Branch

whoops.. That linked patch just implemented the parsing for cross-fade. The final implementation for cross-fade is still coming along. Reopening this pending some more work on the layout and drawing for cross-fade.

Status: RESOLVED → REOPENED
Flags: needinfo?(zekemedley)
Resolution: FIXED → ---

(In reply to Zéfling from comment #26)
I assume you turned on the pref manually? (even with that I cannot reproduce but just checking...)

Given there's implementation work still needed I wouldn't recommend turning on the switch just yet.

(In reply to Emilio Cobos Álvarez (:emilio) from comment #27)

(In reply to Zéfling from comment #26)
I assume you turned on the pref manually? (even with that I cannot reproduce but just checking...)

Given there's implementation work still needed I wouldn't recommend turning on the switch just yet.

Yes, I just wanted to test the rendering of this CSS property and see on css3test.com if it was enabled. ;)

Blocks: cross-fade

I'm going to morph this bug to cover just the CSS parsing stuff for cross-fade and spin off a separate bug for the graphics implementation. Bug 1657516 will track the actual shipping of the feature.

Status: REOPENED → RESOLVED
Closed: 6 months ago5 months ago
Resolution: --- → FIXED
Summary: Implement cross-fade() from CSS Image Values and Replaced Content Module Level 4 → Implement parsing for cross-fade() from CSS Image Values and Replaced Content Module Level 4

(In reply to Zéfling from comment #28)

(In reply to Emilio Cobos Álvarez (:emilio) from comment #27)

(In reply to Zéfling from comment #26)
I assume you turned on the pref manually? (even with that I cannot reproduce but just checking...)

Given there's implementation work still needed I wouldn't recommend turning on the switch just yet.

Yes, I just wanted to test the rendering of this CSS property and see on css3test.com if it was enabled. ;)

If you have any more information about that crash I'd love to look into it. I'm also not able to reproduce it just by toggling the pref and visiting the page, but if there really is a problem there we should make sure its fixed by the time we have a final implementation :)

My only guess based in the crash report: If you modified the example on the page to use the newer cross fade syntax and weren't using webrenderer its possible that somehow the code made it into nsImageRenderer::Draw and StyleImage::IsOpaque where you saw the crash because our implementation isn't complete.

Alias: cross-fade
No longer blocks: css-images-3, css3test

Removing dev-doc-needed from here; we'll track the documentation of this in https://bugzilla.mozilla.org/show_bug.cgi?id=1657516 instead.

Keywords: dev-doc-needed
You need to log in before you can comment on or make changes to this bug.