diff options
author | timothy_horton@apple.com <timothy_horton@apple.com@bbb929c8-8fbe-4397-9dbb-9b2b20218538> | 2011-12-08 23:06:15 +0000 |
---|---|---|
committer | timothy_horton@apple.com <timothy_horton@apple.com@bbb929c8-8fbe-4397-9dbb-9b2b20218538> | 2011-12-08 23:06:15 +0000 |
commit | fa6dfe257fdfd03c593d1915d1c34a0284eb2a65 (patch) | |
tree | 65bcf274f6c61f5cebc0d45dee2dcf9f9d12d354 /third_party/WebKit | |
parent | 9c6a1431ed649a90cf2c73efe65b8b52d728926a (diff) | |
download | chromium_src-fa6dfe257fdfd03c593d1915d1c34a0284eb2a65.zip chromium_src-fa6dfe257fdfd03c593d1915d1c34a0284eb2a65.tar.gz chromium_src-fa6dfe257fdfd03c593d1915d1c34a0284eb2a65.tar.bz2 |
Enable animations of CSS images using -webkit-cross-fade
https://bugs.webkit.org/show_bug.cgi?id=74049
<rdar://problem/10209303>
Reviewed by Simon Fraser.
Add support for animating CSS images in the following properties:
- background(-image)
- border-image(-source)
- list-style(-image)
- -webkit-mask-box-image(-source)
- -webkit-mask-image(-source)
This patch only adds support for transitioning between NinePieceImages
where all of the properties except the image itself are equal, and the
size of the images are equal. Other cases will not animate.
Add animation blend functions for StyleImage and NinePieceImage.
Apply the proper compositing operation to -webkit-cross-fade, and
fix handling of the destination and source areas to support scaling.
Tests: animations/cross-fade-background-image.html
animations/cross-fade-border-image-source.html
animations/cross-fade-list-style-image.html
animations/cross-fade-webkit-mask-box-image.html
animations/cross-fade-webkit-mask-image.html
* css/CSSCrossfadeValue.cpp:
(WebCore::cachedImageForCSSValue):
(WebCore::CSSCrossfadeValue::fixedSize):
(WebCore::CSSCrossfadeValue::image):
* css/CSSImageValue.cpp:
(WebCore::CSSImageValue::CSSImageValue):
* css/CSSImageValue.h:
(WebCore::CSSImageValue::create):
* page/animation/AnimationBase.cpp:
(WebCore::crossfadeBlend):
(WebCore::blendFunc):
(WebCore::RefCountedPropertyWrapper::RefCountedPropertyWrapper):
(WebCore::RefCountedPropertyWrapper::blend):
(WebCore::FillLayerRefCountedPropertyWrapper::FillLayerRefCountedPropertyWrapper):
(WebCore::FillLayerRefCountedPropertyWrapper::blend):
(WebCore::FillLayersPropertyWrapper::FillLayersPropertyWrapper):
(WebCore::AnimationBase::ensurePropertyMap):
(WebCore::addShorthandProperties):
* platform/graphics/CrossfadeGeneratedImage.cpp:
(WebCore::CrossfadeGeneratedImage::drawCrossfade):
(WebCore::CrossfadeGeneratedImage::draw):
(WebCore::CrossfadeGeneratedImage::drawPattern):
* platform/graphics/CrossfadeGeneratedImage.h:
* rendering/style/RenderStyle.h:
(WebCore::InheritedFlags::setMaskImage):
Add tests of -webkit-animation (using -webkit-cross-fade) between:
- background-image
- border-image
- list-style-image
- -webkit-mask-box-image
- -webkit-mask-image
Add the ability for animation tests to compare an animated element to a static element.
Add tests of -webkit-transition (using -webkit-cross-fade) between:
- background-image
- border-image
* animations/cross-fade-background-image-expected.txt: Added.
* animations/cross-fade-background-image.html: Added.
* animations/cross-fade-border-image-source-expected.txt: Added.
* animations/cross-fade-border-image-source.html: Added.
* animations/cross-fade-list-style-image-expected.txt: Added.
* animations/cross-fade-list-style-image.html: Added.
* animations/cross-fade-webkit-mask-box-image-expected.txt: Added.
* animations/cross-fade-webkit-mask-box-image.html: Added.
* animations/cross-fade-webkit-mask-image-expected.txt: Added.
* animations/cross-fade-webkit-mask-image.html: Added.
* animations/resources/animation-test-helpers.js:
(parseCrossFade):
(checkExpectedValue):
* animations/resources/blue-100.png: Added.
* animations/resources/green-100.png: Added.
* animations/resources/stripes-100.png: Added.
* platform/mac/animations/cross-fade-background-image-expected.png: Added.
* platform/mac/animations/cross-fade-border-image-source-expected.png: Added.
* platform/mac/animations/cross-fade-list-style-image-expected.png: Added.
* platform/mac/animations/cross-fade-webkit-mask-box-image-expected.png: Added.
* platform/mac/animations/cross-fade-webkit-mask-image-expected.png: Added.
* platform/mac/transitions/cross-fade-background-image-expected.png: Added.
* platform/mac/transitions/cross-fade-border-image-expected.png: Added.
* transitions/cross-fade-background-image-expected.txt: Added.
* transitions/cross-fade-background-image.html: Added.
* transitions/cross-fade-border-image-expected.txt: Added.
* transitions/cross-fade-border-image.html: Added.
* transitions/resources/transition-test-helpers.js:
(expected):
git-svn-id: svn://svn.chromium.org/blink/trunk@102388 bbb929c8-8fbe-4397-9dbb-9b2b20218538
Diffstat (limited to 'third_party/WebKit')
28 files changed, 857 insertions, 18 deletions
diff --git a/third_party/WebKit/LayoutTests/ChangeLog b/third_party/WebKit/LayoutTests/ChangeLog index b3eff6a..3c198d9 100644 --- a/third_party/WebKit/LayoutTests/ChangeLog +++ b/third_party/WebKit/LayoutTests/ChangeLog @@ -1,3 +1,54 @@ +2011-12-08 Tim Horton <timothy_horton@apple.com> + + Enable animations of CSS images using -webkit-cross-fade + https://bugs.webkit.org/show_bug.cgi?id=74049 + <rdar://problem/10209303> + + Reviewed by Simon Fraser. + + Add tests of -webkit-animation (using -webkit-cross-fade) between: + - background-image + - border-image + - list-style-image + - -webkit-mask-box-image + - -webkit-mask-image + + Add the ability for animation tests to compare an animated element to a static element. + + Add tests of -webkit-transition (using -webkit-cross-fade) between: + - background-image + - border-image + + * animations/cross-fade-background-image-expected.txt: Added. + * animations/cross-fade-background-image.html: Added. + * animations/cross-fade-border-image-source-expected.txt: Added. + * animations/cross-fade-border-image-source.html: Added. + * animations/cross-fade-list-style-image-expected.txt: Added. + * animations/cross-fade-list-style-image.html: Added. + * animations/cross-fade-webkit-mask-box-image-expected.txt: Added. + * animations/cross-fade-webkit-mask-box-image.html: Added. + * animations/cross-fade-webkit-mask-image-expected.txt: Added. + * animations/cross-fade-webkit-mask-image.html: Added. + * animations/resources/animation-test-helpers.js: + (parseCrossFade): + (checkExpectedValue): + * animations/resources/blue-100.png: Added. + * animations/resources/green-100.png: Added. + * animations/resources/stripes-100.png: Added. + * platform/mac/animations/cross-fade-background-image-expected.png: Added. + * platform/mac/animations/cross-fade-border-image-source-expected.png: Added. + * platform/mac/animations/cross-fade-list-style-image-expected.png: Added. + * platform/mac/animations/cross-fade-webkit-mask-box-image-expected.png: Added. + * platform/mac/animations/cross-fade-webkit-mask-image-expected.png: Added. + * platform/mac/transitions/cross-fade-background-image-expected.png: Added. + * platform/mac/transitions/cross-fade-border-image-expected.png: Added. + * transitions/cross-fade-background-image-expected.txt: Added. + * transitions/cross-fade-background-image.html: Added. + * transitions/cross-fade-border-image-expected.txt: Added. + * transitions/cross-fade-border-image.html: Added. + * transitions/resources/transition-test-helpers.js: + (expected): + 2011-12-08 Chris Fleizach <cfleizach@apple.com> platform/mac/accessibility/search-with-frames.html crashes diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-background-image-expected.txt b/third_party/WebKit/LayoutTests/animations/cross-fade-background-image-expected.txt new file mode 100644 index 0000000..216e053 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-background-image-expected.txt @@ -0,0 +1,21 @@ +layer at (0,0) size 800x600 + RenderView at (0,0) size 800x600 +layer at (0,0) size 800x600 + RenderBlock {HTML} at (0,0) size 800x600 + RenderBody {BODY} at (8,8) size 784x584 + RenderBlock {DIV} at (0,0) size 784x54 + RenderText {#text} at (0,0) size 577x18 + text run at (0,0) width 577: "PASS - \"backgroundImage\" property for \"box\" element at 2.5s saw something close to: 0.5" + RenderBR {BR} at (577,14) size 0x0 + RenderText {#text} at (0,18) size 704x18 + text run at (0,18) width 704: "PASS - \"backgroundImage\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other" + RenderBR {BR} at (704,32) size 0x0 + RenderText {#text} at (0,36) size 769x18 + text run at (0,36) width 769: "PASS - \"backgroundImage\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other" + RenderBR {BR} at (769,50) size 0x0 +layer at (100,100) size 100x100 + RenderBlock (positioned) {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] +layer at (100,300) size 100x100 + RenderBlock (positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000] +layer at (100,200) size 100x100 + RenderBlock (positioned) {DIV} at (100,200) size 100x100 diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-background-image.html b/third_party/WebKit/LayoutTests/animations/cross-fade-background-image.html new file mode 100644 index 0000000..595ed55 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-background-image.html @@ -0,0 +1,60 @@ +<html> +<head> + <style> + #box { + position: absolute; + left: 100px; + top: 100px; + height: 100px; + width: 100px; + background-color: red; + -webkit-animation: anim 1s linear infinite; + } + #boxShorthand { + position: absolute; + left: 100px; + top: 200px; + height: 100px; + width: 100px; + background-color: red; + -webkit-animation: animShorthand 1s linear infinite; + } + #boxStatic { + position: absolute; + left: 100px; + top: 300px; + height: 100px; + width: 100px; + background-color: red; + background-image: -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 50%); + } + @-webkit-keyframes anim { + from { background-image: url(resources/blue-100.png); } + to { background-image: url(resources/green-100.png); } + } + @-webkit-keyframes animShorthand { + from { background: url(resources/blue-100.png); } + to { background: url(resources/green-100.png); } + } + </style> + <script src="resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script> + <script type="text/javascript" charset="utf-8"> + const expectedValues = [ + // [animation-name, time, element-id, property, expected-value, tolerance] + ["anim", 2.5, "box", "backgroundImage", 0.5, 0.05], + ["anim", 2.5, ["box", "static:boxStatic"], "backgroundImage", 0.5, 0.05], + ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "backgroundImage", 0.5, 0.05], + ]; + + var doPixelTest = true; + var disablePauseAPI = false; + runAnimationTest(expectedValues, null, undefined, disablePauseAPI, doPixelTest); + </script> +</head> +<body> +<div id="box"></div> +<div id="boxStatic"></div> +<div id="boxShorthand"></div> +<div id="result"></div> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-border-image-source-expected.txt b/third_party/WebKit/LayoutTests/animations/cross-fade-border-image-source-expected.txt new file mode 100644 index 0000000..9f1282f --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-border-image-source-expected.txt @@ -0,0 +1,21 @@ +layer at (0,0) size 800x600 + RenderView at (0,0) size 800x600 +layer at (0,0) size 800x600 + RenderBlock {HTML} at (0,0) size 800x600 + RenderBody {BODY} at (8,8) size 784x584 + RenderBlock {DIV} at (0,0) size 784x54 + RenderText {#text} at (0,0) size 587x18 + text run at (0,0) width 587: "PASS - \"borderImageSource\" property for \"box\" element at 2.5s saw something close to: 0.5" + RenderBR {BR} at (587,14) size 0x0 + RenderText {#text} at (0,18) size 714x18 + text run at (0,18) width 714: "PASS - \"borderImageSource\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other" + RenderBR {BR} at (714,32) size 0x0 + RenderText {#text} at (0,36) size 779x18 + text run at (0,36) width 779: "PASS - \"borderImageSource\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other" + RenderBR {BR} at (779,50) size 0x0 +layer at (100,100) size 106x106 + RenderBlock (positioned) {DIV} at (100,100) size 106x106 [bgcolor=#008000] [border:] +layer at (100,250) size 106x106 + RenderBlock (positioned) {DIV} at (100,250) size 106x106 [bgcolor=#008000] [border:] +layer at (100,400) size 106x106 + RenderBlock (positioned) {DIV} at (100,400) size 106x106 [bgcolor=#008000] [border:] diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-border-image-source.html b/third_party/WebKit/LayoutTests/animations/cross-fade-border-image-source.html new file mode 100644 index 0000000..4e68a4b --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-border-image-source.html @@ -0,0 +1,62 @@ +<html> +<head> + <style> + #box { + position: absolute; + left: 100px; + top: 100px; + height: 100px; + width: 100px; + background-color: green; + -webkit-animation: anim 1s linear infinite; + border-image: url() 5 5 5 5 /20px stretch stretch; + } + #boxShorthand { + position: absolute; + left: 100px; + top: 250px; + height: 100px; + width: 100px; + background-color: green; + -webkit-animation: animShorthand 1s linear infinite; + } + #boxStatic { + position: absolute; + left: 100px; + top: 400px; + height: 100px; + width: 100px; + background-color: green; + border-image: -webkit-cross-fade(url(resources/stripes-100.png), url(resources/green-100.png), 50%) 5 5 5 5 /20px stretch stretch; + } + @-webkit-keyframes anim { + from { border-image-source: url(resources/stripes-100.png); } + to { border-image-source: url(resources/green-100.png); } + } + @-webkit-keyframes animShorthand { + from { border-image: url(resources/stripes-100.png) 5 5 5 5 /20px stretch stretch; } + to { border-image: url(resources/green-100.png) 5 5 5 5 /20px stretch stretch; } + } + </style> + <script src="resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script> + <script type="text/javascript" charset="utf-8"> + const expectedValues = [ + // [animation-name, time, element-id, property, expected-value, tolerance] + // FIXME: We can't test reading the borderImage shorthand because of bug #13658. + ["anim", 2.5, "box", "borderImageSource", 0.5, 0.05], + ["anim", 2.5, ["box", "static:boxStatic"], "borderImageSource", 0.5, 0.05], + ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "borderImageSource", 0.5, 0.05], + ]; + + var doPixelTest = true; + var disablePauseAPI = false; + runAnimationTest(expectedValues, null, undefined, disablePauseAPI, doPixelTest); + </script> +</head> +<body> +<div id="box"></div> +<div id="boxShorthand"></div> +<div id="boxStatic"></div> +<div id="result"></div> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-list-style-image-expected.txt b/third_party/WebKit/LayoutTests/animations/cross-fade-list-style-image-expected.txt new file mode 100644 index 0000000..fd66054 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-list-style-image-expected.txt @@ -0,0 +1,45 @@ +layer at (0,0) size 800x600 + RenderView at (0,0) size 800x600 +layer at (0,0) size 800x600 + RenderBlock {HTML} at (0,0) size 800x600 + RenderBody {BODY} at (8,8) size 784x584 + RenderBlock {DIV} at (0,0) size 784x54 + RenderText {#text} at (0,0) size 552x18 + text run at (0,0) width 552: "PASS - \"listStyleImage\" property for \"box\" element at 2.5s saw something close to: 0.5" + RenderBR {BR} at (552,14) size 0x0 + RenderText {#text} at (0,18) size 679x18 + text run at (0,18) width 679: "PASS - \"listStyleImage\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other" + RenderBR {BR} at (679,32) size 0x0 + RenderText {#text} at (0,36) size 744x18 + text run at (0,36) width 744: "PASS - \"listStyleImage\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other" + RenderBR {BR} at (744,50) size 0x0 +layer at (100,116) size 140x100 + RenderBlock (positioned) {UL} at (100,116) size 140x100 + RenderListItem {LI} at (40,0) size 100x104 + RenderListMarker at (-107,0) size 100x100 + RenderText {#text} at (0,86) size 23x18 + text run at (0,86) width 23: "one" + RenderListItem {LI} at (40,104) size 100x104 + RenderListMarker at (-107,0) size 100x100 + RenderText {#text} at (0,86) size 24x18 + text run at (0,86) width 24: "two" +layer at (100,366) size 140x100 + RenderBlock (positioned) {UL} at (100,366) size 140x100 + RenderListItem {LI} at (40,0) size 100x104 + RenderListMarker at (-107,0) size 100x100 + RenderText {#text} at (0,86) size 23x18 + text run at (0,86) width 23: "one" + RenderListItem {LI} at (40,104) size 100x104 + RenderListMarker at (-107,0) size 100x100 + RenderText {#text} at (0,86) size 24x18 + text run at (0,86) width 24: "two" +layer at (400,116) size 140x100 + RenderBlock (positioned) {UL} at (400,116) size 140x100 + RenderListItem {LI} at (40,0) size 100x104 + RenderListMarker at (-107,0) size 100x100 + RenderText {#text} at (0,86) size 23x18 + text run at (0,86) width 23: "one" + RenderListItem {LI} at (40,104) size 100x104 + RenderListMarker at (-107,0) size 100x100 + RenderText {#text} at (0,86) size 24x18 + text run at (0,86) width 24: "two" diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-list-style-image.html b/third_party/WebKit/LayoutTests/animations/cross-fade-list-style-image.html new file mode 100644 index 0000000..8610af2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-list-style-image.html @@ -0,0 +1,57 @@ +<html> +<head> + <style> + #box { + position: absolute; + left: 100px; + top: 100px; + height: 100px; + width: 100px; + -webkit-animation: anim 1s linear infinite; + } + #boxShorthand { + position: absolute; + left: 400px; + top: 100px; + height: 100px; + width: 100px; + -webkit-animation: animShorthand 1s linear infinite; + } + #boxStatic { + position: absolute; + left: 100px; + top: 350px; + height: 100px; + width: 100px; + list-style: square -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 50%); + } + @-webkit-keyframes anim { + from { list-style-image: url(resources/blue-100.png); } + to { list-style-image: url(resources/green-100.png); } + } + @-webkit-keyframes animShorthand { + from { list-style: square url(resources/blue-100.png); } + to { list-style: square url(resources/green-100.png); } + } + </style> + <script src="resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script> + <script type="text/javascript" charset="utf-8"> + const expectedValues = [ + // [animation-name, time, element-id, property, expected-value, tolerance] + ["anim", 2.5, "box", "listStyleImage", 0.5, 0.05], + ["anim", 2.5, ["box", "static:boxStatic"], "listStyleImage", 0.5, 0.05], + ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "listStyleImage", 0.5, 0.05], + ]; + + var doPixelTest = true; + var disablePauseAPI = false; + runAnimationTest(expectedValues, null, undefined, disablePauseAPI, doPixelTest); + </script> +</head> +<body> +<ul id="box"><li>one</li><li>two</li></ul> +<ul id="boxStatic"><li>one</li><li>two</li></ul> +<ul id="boxShorthand"><li>one</li><li>two</li></ul> +<div id="result"></div> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-box-image-expected.txt b/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-box-image-expected.txt new file mode 100644 index 0000000..587a619 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-box-image-expected.txt @@ -0,0 +1,16 @@ +layer at (0,0) size 800x600 + RenderView at (0,0) size 800x600 +layer at (0,0) size 800x600 + RenderBlock {HTML} at (0,0) size 800x600 + RenderBody {BODY} at (8,8) size 784x584 + RenderBlock {DIV} at (0,0) size 784x36 + RenderText {#text} at (0,0) size 623x18 + text run at (0,0) width 623: "PASS - \"webkitMaskBoxImage\" property for \"box\" element at 2.25s saw something close to: 0.25" + RenderBR {BR} at (623,14) size 0x0 + RenderText {#text} at (0,18) size 742x18 + text run at (0,18) width 742: "PASS - \"webkitMaskBoxImage\" property for \"box\" and \"boxStatic\" elements at 2.25s are close enough to each other" + RenderBR {BR} at (742,32) size 0x0 +layer at (100,100) size 200x200 + RenderImage {IMG} at (100,100) size 200x200 [bgcolor=#FF0000] +layer at (100,300) size 200x200 + RenderImage {IMG} at (100,300) size 200x200 [bgcolor=#FF0000] diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-box-image.html b/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-box-image.html new file mode 100644 index 0000000..5776ce4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-box-image.html @@ -0,0 +1,45 @@ +<html> +<head> + <style> + #box { + position: absolute; + left: 100px; + top: 100px; + height: 200px; + width: 200px; + background-color: red; + -webkit-animation: anim 1s linear infinite; + } + #boxStatic { + position: absolute; + left: 100px; + top: 300px; + height: 200px; + width: 200px; + background-color: red; + -webkit-mask-box-image: -webkit-cross-fade(url(resources/stripes-100.png), url(resources/green-100.png), 25%) 75 stretch; + } + @-webkit-keyframes anim { + from { -webkit-mask-box-image: url(resources/stripes-100.png) 75 stretch; } + to { -webkit-mask-box-image: url(resources/green-100.png) 75 stretch; } + } + </style> + <script src="resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script> + <script type="text/javascript" charset="utf-8"> + const expectedValues = [ + // [animation-name, time, element-id, property, expected-value, tolerance] + ["anim", 2.25, "box", "webkitMaskBoxImage", 0.25, 0.05], + ["anim", 2.25, ["box", "static:boxStatic"], "webkitMaskBoxImage", 0.25, 0.05] + ]; + + var doPixelTest = true; + var disablePauseAPI = false; + runAnimationTest(expectedValues, null, undefined, disablePauseAPI, doPixelTest); + </script> +</head> +<body> +<img id="box" src="resources/green-100.png"/> +<img id="boxStatic" src="resources/green-100.png"/> +<div id="result"></div> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-image-expected.txt b/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-image-expected.txt new file mode 100644 index 0000000..91ed8ce --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-image-expected.txt @@ -0,0 +1,16 @@ +layer at (0,0) size 800x600 + RenderView at (0,0) size 800x600 +layer at (0,0) size 800x600 + RenderBlock {HTML} at (0,0) size 800x600 + RenderBody {BODY} at (8,8) size 784x584 + RenderBlock {DIV} at (0,0) size 784x36 + RenderText {#text} at (0,0) size 596x18 + text run at (0,0) width 596: "PASS - \"webkitMaskImage\" property for \"box\" element at 2.25s saw something close to: 0.25" + RenderBR {BR} at (596,14) size 0x0 + RenderText {#text} at (0,18) size 715x18 + text run at (0,18) width 715: "PASS - \"webkitMaskImage\" property for \"box\" and \"boxStatic\" elements at 2.25s are close enough to each other" + RenderBR {BR} at (715,32) size 0x0 +layer at (100,100) size 100x100 + RenderImage {IMG} at (100,100) size 100x100 [bgcolor=#FF0000] +layer at (100,200) size 100x100 + RenderImage {IMG} at (100,200) size 100x100 [bgcolor=#FF0000] diff --git a/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-image.html b/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-image.html new file mode 100644 index 0000000..aa70ff4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/cross-fade-webkit-mask-image.html @@ -0,0 +1,45 @@ +<html> +<head> + <style> + #box { + position: absolute; + left: 100px; + top: 100px; + height: 100px; + width: 100px; + background-color: red; + -webkit-animation: anim 1s linear infinite; + } + #boxStatic { + position: absolute; + left: 100px; + top: 200px; + height: 100px; + width: 100px; + background-color: red; + -webkit-mask-image: -webkit-cross-fade(url(resources/stripes-100.png), url(resources/green-100.png), 25%); + } + @-webkit-keyframes anim { + from { -webkit-mask-image: url(resources/stripes-100.png); } + to { -webkit-mask-image: url(resources/green-100.png); } + } + </style> + <script src="resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script> + <script type="text/javascript" charset="utf-8"> + const expectedValues = [ + // [animation-name, time, element-id, property, expected-value, tolerance] + ["anim", 2.25, "box", "webkitMaskImage", 0.25, 0.05], + ["anim", 2.25, ["box", "static:boxStatic"], "webkitMaskImage", 0.25, 0.05] + ]; + + var doPixelTest = true; + var disablePauseAPI = false; + runAnimationTest(expectedValues, null, undefined, disablePauseAPI, doPixelTest); + </script> +</head> +<body> +<img id="box" src="resources/green-100.png"/> +<img id="boxStatic" src="resources/green-100.png"/> +<div id="result"></div> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/animations/resources/animation-test-helpers.js b/third_party/WebKit/LayoutTests/animations/resources/animation-test-helpers.js index e15e1b0..76351ef 100644 --- a/third_party/WebKit/LayoutTests/animations/resources/animation-test-helpers.js +++ b/third_party/WebKit/LayoutTests/animations/resources/animation-test-helpers.js @@ -22,7 +22,8 @@ Function parameters: [2] If a single string is passed, it is the id of the element to test. If an array with 2 elements is passed they are the ids of 2 elements, whose values are compared for equality. In this case the expected value is ignored - but the tolerance is used in the comparison. + but the tolerance is used in the comparison. If the second element is prefixed with "static:", no animation on that + element is required, allowing comparison with an unanimated "expected value" element. If a string with a '.' is passed, this is an element in an iframe. The string before the dot is the iframe id and the string after the dot is the element name in that iframe. @@ -48,6 +49,16 @@ function matrixStringToArray(s) return m[0].split(","); } +function parseCrossFade(s) +{ + var matches = s.match("-webkit-cross-fade\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\)"); + + if (!matches) + return null; + + return {"from": matches[1], "to": matches[2], "percent": parseFloat(matches[3])} +} + function checkExpectedValue(expected, index) { var animationName = expected[index][0]; @@ -59,6 +70,7 @@ function checkExpectedValue(expected, index) // Check for a pair of element Ids var compareElements = false; + var element2Static = false; var elementId2; if (typeof elementId != "string") { if (elementId.length != 2) @@ -66,6 +78,12 @@ function checkExpectedValue(expected, index) elementId2 = elementId[1]; elementId = elementId[0]; + + if (elementId2.indexOf("static:") == 0) { + elementId2 = elementId2.replace("static:", ""); + element2Static = true; + } + compareElements = true; } @@ -84,7 +102,7 @@ function checkExpectedValue(expected, index) return; } - if (compareElements && animationName && hasPauseAnimationAPI && !layoutTestController.pauseAnimationAtTimeOnElementWithId(animationName, time, elementId2)) { + if (compareElements && !element2Static && animationName && hasPauseAnimationAPI && !layoutTestController.pauseAnimationAtTimeOnElementWithId(animationName, time, elementId2)) { result += "FAIL - animation \"" + animationName + "\" is not running" + "<br>"; return; } @@ -140,6 +158,38 @@ function checkExpectedValue(expected, index) } else pass = isCloseEnough(computedValue, expectedValue, tolerance); + } else if (property == "backgroundImage" + || property == "borderImageSource" + || property == "listStyleImage" + || property == "webkitMaskImage" + || property == "webkitMaskBoxImage") { + var element; + if (iframeId) + element = document.getElementById(iframeId).contentDocument.getElementById(elementId); + else + element = document.getElementById(elementId); + + computedValue = window.getComputedStyle(element)[property]; + computedCrossFade = parseCrossFade(computedValue); + + if (!computedCrossFade) { + pass = false; + } else { + if (compareElements) { + computedValue2 = window.getComputedStyle(document.getElementById(elementId2))[property]; + computedCrossFade2 = parseCrossFade(computedValue2); + if (computedCrossFade2) { + pass = (isCloseEnough(computedCrossFade.percent, computedCrossFade2.percent, tolerance) && + computedCrossFade.from == computedCrossFade2.from && + computedCrossFade.to == computedCrossFade2.to); + } + else { + pass = false; + } + } else { + pass = isCloseEnough(computedCrossFade.percent, expectedValue, tolerance); + } + } } else { var element; if (iframeId) diff --git a/third_party/WebKit/LayoutTests/animations/resources/blue-100.png b/third_party/WebKit/LayoutTests/animations/resources/blue-100.png Binary files differnew file mode 100644 index 0000000..f578ae7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/resources/blue-100.png diff --git a/third_party/WebKit/LayoutTests/animations/resources/green-100.png b/third_party/WebKit/LayoutTests/animations/resources/green-100.png Binary files differnew file mode 100644 index 0000000..e45bbbe --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/resources/green-100.png diff --git a/third_party/WebKit/LayoutTests/animations/resources/stripes-100.png b/third_party/WebKit/LayoutTests/animations/resources/stripes-100.png Binary files differnew file mode 100644 index 0000000..cfb6980 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/resources/stripes-100.png diff --git a/third_party/WebKit/LayoutTests/transitions/cross-fade-background-image-expected.txt b/third_party/WebKit/LayoutTests/transitions/cross-fade-background-image-expected.txt new file mode 100644 index 0000000..8be0e3e --- /dev/null +++ b/third_party/WebKit/LayoutTests/transitions/cross-fade-background-image-expected.txt @@ -0,0 +1,14 @@ +layer at (0,0) size 800x600 + RenderView at (0,0) size 800x600 +layer at (0,0) size 800x600 + RenderBlock {HTML} at (0,0) size 800x600 + RenderBody {BODY} at (8,10) size 784x582 + RenderBlock {DIV} at (10,0) size 200x200 + RenderBlock {DIV} at (10,210) size 200x200 + RenderBlock {DIV} at (0,420) size 784x36 + RenderText {#text} at (0,0) size 581x18 + text run at (0,0) width 581: "PASS - \"background-image\" property for \"box\" element at 0.5s saw something close to: 0.5" + RenderBR {BR} at (581,14) size 0x0 + RenderText {#text} at (0,18) size 646x18 + text run at (0,18) width 646: "PASS - \"background-image\" property for \"boxShorthand\" element at 0.5s saw something close to: 0.5" + RenderBR {BR} at (646,32) size 0x0 diff --git a/third_party/WebKit/LayoutTests/transitions/cross-fade-background-image.html b/third_party/WebKit/LayoutTests/transitions/cross-fade-background-image.html new file mode 100644 index 0000000..b8d70a2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/transitions/cross-fade-background-image.html @@ -0,0 +1,57 @@ +<!DOCTYPE> + +<html> +<head> + <style> + .box { + height: 200px; + width: 200px; + margin: 10px; + -webkit-transition-duration: 1s; + -webkit-transition-timing-function: linear; + } + + #box { + background-image: url('../fast/backgrounds/repeat/resources/gradient.gif'); + -webkit-transition-property: background-image; + } + + #box.final { + background-image: url('../fast/backgrounds/repeat/resources/nav.blue.gif'); + } + + #boxShorthand { + background: url('../fast/backgrounds/repeat/resources/gradient.gif'); + -webkit-transition-property: background; + } + + #boxShorthand.final { + background: url('../fast/backgrounds/repeat/resources/nav.blue.gif'); + } + + </style> + <script src="resources/transition-test-helpers.js" type="text/javascript"></script> + <script> + + const expectedValues = [ + // [time, element-id, property, expected-value, tolerance] + [0.5, 'box', 'background-image', 0.5, 0.05], + [0.5, 'boxShorthand', 'background-image', 0.5, 0.05], + ]; + + function setupTest() + { + document.getElementById('box').className = 'box final'; + document.getElementById('boxShorthand').className = 'box final'; + } + + runTransitionTest(expectedValues, setupTest, usePauseAPI, true); + </script> +</head> +<body> + <div id="box" class="box"></div> + <div id="boxShorthand" class="box"></div> + + <div id="result"></div> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/transitions/cross-fade-border-image-expected.txt b/third_party/WebKit/LayoutTests/transitions/cross-fade-border-image-expected.txt new file mode 100644 index 0000000..90caa23 --- /dev/null +++ b/third_party/WebKit/LayoutTests/transitions/cross-fade-border-image-expected.txt @@ -0,0 +1,14 @@ +layer at (0,0) size 800x600 + RenderView at (0,0) size 800x600 +layer at (0,0) size 800x600 + RenderBlock {HTML} at (0,0) size 800x600 + RenderBody {BODY} at (8,10) size 784x582 + RenderBlock {DIV} at (10,0) size 206x206 [border:] + RenderBlock {DIV} at (10,216) size 206x206 [border:] + RenderBlock {DIV} at (0,432) size 784x36 + RenderText {#text} at (0,0) size 593x18 + text run at (0,0) width 593: "PASS - \"border-image-source\" property for \"box\" element at 0.5s saw something close to: 0.5" + RenderBR {BR} at (593,14) size 0x0 + RenderText {#text} at (0,18) size 658x18 + text run at (0,18) width 658: "PASS - \"border-image-source\" property for \"boxShorthand\" element at 0.5s saw something close to: 0.5" + RenderBR {BR} at (658,32) size 0x0 diff --git a/third_party/WebKit/LayoutTests/transitions/cross-fade-border-image.html b/third_party/WebKit/LayoutTests/transitions/cross-fade-border-image.html new file mode 100644 index 0000000..87dc007 --- /dev/null +++ b/third_party/WebKit/LayoutTests/transitions/cross-fade-border-image.html @@ -0,0 +1,57 @@ +<!DOCTYPE> + +<html> +<head> + <style> + .box { + height: 200px; + width: 200px; + margin: 10px; + -webkit-transition-duration: 1s; + -webkit-transition-timing-function: linear; + } + + #box { + border-image: url('../animations/resources/blue-100.png') 5 5 5 5 /40px stretch stretch; + -webkit-transition-property: border-image-source; + } + + #box.final { + border-image-source: url('../animations/resources/stripes-100.png'); + } + + #boxShorthand { + border-image: url('../animations/resources/blue-100.png') 5 5 5 5 /40px stretch stretch; + -webkit-transition-property: border-image; + } + + #boxShorthand.final { + border-image: url('../animations/resources/stripes-100.png') 5 5 5 5 /40px stretch stretch; + } + + </style> + <script src="resources/transition-test-helpers.js" type="text/javascript"></script> + <script> + + const expectedValues = [ + // [time, element-id, property, expected-value, tolerance] + [0.5, 'box', 'border-image-source', 0.5, 0.05], + [0.5, 'boxShorthand', 'border-image', 0.5, 0.05], + ]; + + function setupTest() + { + document.getElementById('box').className = 'box final'; + document.getElementById('boxShorthand').className = 'box final'; + } + + runTransitionTest(expectedValues, setupTest, usePauseAPI, true); + </script> +</head> +<body> + <div id="box" class="box"></div> + <div id="boxShorthand" class="box"></div> + + <div id="result"></div> +</body> +</html> diff --git a/third_party/WebKit/LayoutTests/transitions/resources/transition-test-helpers.js b/third_party/WebKit/LayoutTests/transitions/resources/transition-test-helpers.js index d67a41e..fd83147 100644 --- a/third_party/WebKit/LayoutTests/transitions/resources/transition-test-helpers.js +++ b/third_party/WebKit/LayoutTests/transitions/resources/transition-test-helpers.js @@ -59,6 +59,16 @@ function compareRGB(rgb, expected, tolerance) isCloseEnough(parseInt(rgb[2]), expected[2], tolerance)); } +function parseCrossFade(s) +{ + var matches = s.match("-webkit-cross-fade\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\)"); + + if (!matches) + return null; + + return {"from": matches[1], "to": matches[2], "percent": parseFloat(matches[3])} +} + function checkExpectedValue(expected, index) { var time = expected[index][0]; @@ -109,6 +119,23 @@ function checkExpectedValue(expected, index) } else if (property == "lineHeight") { computedValue = parseInt(window.getComputedStyle(document.getElementById(elementId)).lineHeight); pass = isCloseEnough(computedValue, expectedValue, tolerance); + } else if (property == "background-image" + || property == "border-image-source" + || property == "border-image" + || property == "list-style-image" + || property == "-webkit-mask-image" + || property == "-webkit-mask-box-image") { + if (property == "border-image" || property == "-webkit-mask-image" || property == "-webkit-mask-box-image") + property += "-source"; + + computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property).cssText; + computedCrossFade = parseCrossFade(computedValue); + + if (!computedCrossFade) { + pass = false; + } else { + pass = isCloseEnough(computedCrossFade.percent, expectedValue, tolerance); + } } else { var computedStyle = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property); if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) { diff --git a/third_party/WebKit/Source/WebCore/ChangeLog b/third_party/WebKit/Source/WebCore/ChangeLog index 8d1a118..4622350 100644 --- a/third_party/WebKit/Source/WebCore/ChangeLog +++ b/third_party/WebKit/Source/WebCore/ChangeLog @@ -1,3 +1,59 @@ +2011-12-08 Tim Horton <timothy_horton@apple.com> + + Enable animations of CSS images using -webkit-cross-fade + https://bugs.webkit.org/show_bug.cgi?id=74049 + <rdar://problem/10209303> + + Reviewed by Simon Fraser. + + Add support for animating CSS images in the following properties: + - background(-image) + - border-image(-source) + - list-style(-image) + - -webkit-mask-box-image(-source) + - -webkit-mask-image(-source) + + This patch only adds support for transitioning between NinePieceImages + where all of the properties except the image itself are equal, and the + size of the images are equal. Other cases will not animate. + + Add animation blend functions for StyleImage and NinePieceImage. + + Apply the proper compositing operation to -webkit-cross-fade, and + fix handling of the destination and source areas to support scaling. + + Tests: animations/cross-fade-background-image.html + animations/cross-fade-border-image-source.html + animations/cross-fade-list-style-image.html + animations/cross-fade-webkit-mask-box-image.html + animations/cross-fade-webkit-mask-image.html + + * css/CSSCrossfadeValue.cpp: + (WebCore::cachedImageForCSSValue): + (WebCore::CSSCrossfadeValue::fixedSize): + (WebCore::CSSCrossfadeValue::image): + * css/CSSImageValue.cpp: + (WebCore::CSSImageValue::CSSImageValue): + * css/CSSImageValue.h: + (WebCore::CSSImageValue::create): + * page/animation/AnimationBase.cpp: + (WebCore::crossfadeBlend): + (WebCore::blendFunc): + (WebCore::RefCountedPropertyWrapper::RefCountedPropertyWrapper): + (WebCore::RefCountedPropertyWrapper::blend): + (WebCore::FillLayerRefCountedPropertyWrapper::FillLayerRefCountedPropertyWrapper): + (WebCore::FillLayerRefCountedPropertyWrapper::blend): + (WebCore::FillLayersPropertyWrapper::FillLayersPropertyWrapper): + (WebCore::AnimationBase::ensurePropertyMap): + (WebCore::addShorthandProperties): + * platform/graphics/CrossfadeGeneratedImage.cpp: + (WebCore::CrossfadeGeneratedImage::drawCrossfade): + (WebCore::CrossfadeGeneratedImage::draw): + (WebCore::CrossfadeGeneratedImage::drawPattern): + * platform/graphics/CrossfadeGeneratedImage.h: + * rendering/style/RenderStyle.h: + (WebCore::InheritedFlags::setMaskImage): + 2011-12-08 Stephen White <senorblanco@chromium.org> Use Skia's implementation of Gaussian blur when accelerated filters diff --git a/third_party/WebKit/Source/WebCore/css/CSSCrossfadeValue.cpp b/third_party/WebKit/Source/WebCore/css/CSSCrossfadeValue.cpp index 9bdca47..4ff08af 100644 --- a/third_party/WebKit/Source/WebCore/css/CSSCrossfadeValue.cpp +++ b/third_party/WebKit/Source/WebCore/css/CSSCrossfadeValue.cpp @@ -52,6 +52,9 @@ static bool subimageIsPending(CSSValue* value) static CachedImage* cachedImageForCSSValue(CSSValue* value, CachedResourceLoader* cachedResourceLoader) { + if (!value) + return 0; + if (value->isImageValue()) { StyleCachedImage* styleCachedImage = static_cast<CSSImageValue*>(value)->cachedImage(cachedResourceLoader); if (!styleCachedImage) @@ -104,6 +107,11 @@ IntSize CSSCrossfadeValue::fixedSize(const RenderObject* renderer) IntSize fromImageSize = cachedFromImage->imageForRenderer(renderer)->size(); IntSize toImageSize = cachedToImage->imageForRenderer(renderer)->size(); + // Rounding issues can cause transitions between images of equal size to return + // a different fixed size; avoid performing the interpolation if the images are the same size. + if (fromImageSize == toImageSize) + return fromImageSize; + return IntSize(fromImageSize.width() * inversePercentage + toImageSize.width() * percentage, fromImageSize.height() * inversePercentage + toImageSize.height() * percentage); } @@ -146,7 +154,7 @@ PassRefPtr<Image> CSSCrossfadeValue::image(RenderObject* renderer, const IntSize m_generatedImage = CrossfadeGeneratedImage::create(fromImage, toImage, m_percentageValue->getFloatValue(), fixedSize(renderer), size); - return m_generatedImage.get(); + return m_generatedImage.release(); } void CSSCrossfadeValue::crossfadeChanged(const IntRect&) diff --git a/third_party/WebKit/Source/WebCore/css/CSSImageValue.cpp b/third_party/WebKit/Source/WebCore/css/CSSImageValue.cpp index 22e90b2..8437f3e 100644 --- a/third_party/WebKit/Source/WebCore/css/CSSImageValue.cpp +++ b/third_party/WebKit/Source/WebCore/css/CSSImageValue.cpp @@ -50,6 +50,13 @@ CSSImageValue::CSSImageValue(const String& url) { } +CSSImageValue::CSSImageValue(const String& url, StyleImage* image) + : CSSPrimitiveValue(ImageClass, url, CSS_URI) + , m_image(image) + , m_accessedImage(true) +{ +} + CSSImageValue::~CSSImageValue() { } diff --git a/third_party/WebKit/Source/WebCore/css/CSSImageValue.h b/third_party/WebKit/Source/WebCore/css/CSSImageValue.h index 5a6be8f..82e34de 100644 --- a/third_party/WebKit/Source/WebCore/css/CSSImageValue.h +++ b/third_party/WebKit/Source/WebCore/css/CSSImageValue.h @@ -34,6 +34,7 @@ class CSSImageValue : public CSSPrimitiveValue { public: static PassRefPtr<CSSImageValue> create() { return adoptRef(new CSSImageValue); } static PassRefPtr<CSSImageValue> create(const String& url) { return adoptRef(new CSSImageValue(url)); } + static PassRefPtr<CSSImageValue> create(const String& url, StyleImage* image) { return adoptRef(new CSSImageValue(url, image)); } ~CSSImageValue(); StyleCachedImage* cachedImage(CachedResourceLoader*); @@ -50,6 +51,7 @@ protected: private: CSSImageValue(); explicit CSSImageValue(const String& url); + explicit CSSImageValue(const String& url, StyleImage*); RefPtr<StyleImage> m_image; bool m_accessedImage; diff --git a/third_party/WebKit/Source/WebCore/page/animation/AnimationBase.cpp b/third_party/WebKit/Source/WebCore/page/animation/AnimationBase.cpp index 0595016..453ea85 100644 --- a/third_party/WebKit/Source/WebCore/page/animation/AnimationBase.cpp +++ b/third_party/WebKit/Source/WebCore/page/animation/AnimationBase.cpp @@ -30,6 +30,10 @@ #include "AnimationBase.h" #include "AnimationControllerPrivate.h" +#include "CSSCrossfadeValue.h" +#include "CSSImageGeneratorValue.h" +#include "CSSImageValue.h" +#include "CSSPrimitiveValue.h" #include "CSSPropertyLonghand.h" #include "CSSPropertyNames.h" #include "CompositeAnimation.h" @@ -43,6 +47,8 @@ #include "RenderLayer.h" #include "RenderLayerBacking.h" #include "RenderStyle.h" +#include "StyleCachedImage.h" +#include "StyleGeneratedImage.h" #include "UnitBezier.h" #include <algorithm> #include <wtf/CurrentTime.h> @@ -224,6 +230,58 @@ static inline SVGLength blendFunc(const AnimationBase*, const SVGLength& from, c } #endif +static inline PassRefPtr<StyleImage> crossfadeBlend(const AnimationBase*, StyleCachedImage* fromStyleImage, StyleCachedImage* toStyleImage, double progress) +{ + // If progress is at one of the extremes, we want getComputedStyle to show the image, + // not a completed cross-fade, so we hand back one of the existing images. + if (!progress) + return fromStyleImage; + if (progress == 1) + return toStyleImage; + + CachedImage* fromCachedImage = static_cast<CachedImage*>(fromStyleImage->data()); + CachedImage* toCachedImage = static_cast<CachedImage*>(toStyleImage->data()); + + RefPtr<CSSImageValue> fromImageValue = CSSImageValue::create(fromCachedImage->url(), fromStyleImage); + RefPtr<CSSImageValue> toImageValue = CSSImageValue::create(toCachedImage->url(), toStyleImage); + RefPtr<CSSCrossfadeValue> crossfadeValue = CSSCrossfadeValue::create(fromImageValue, toImageValue); + + crossfadeValue->setPercentage(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER)); + + return StyleGeneratedImage::create(crossfadeValue.get()); +} + +static inline PassRefPtr<StyleImage> blendFunc(const AnimationBase* anim, StyleImage* from, StyleImage* to, double progress) +{ + if (!from || !to) + return to; + + if (from->isCachedImage() && to->isCachedImage()) + return crossfadeBlend(anim, static_cast<StyleCachedImage*>(from), static_cast<StyleCachedImage*>(to), progress); + + // FIXME: Support transitioning generated images as well. (gradients, etc.) + + return to; +} + +static inline NinePieceImage blendFunc(const AnimationBase* anim, const NinePieceImage& from, const NinePieceImage& to, double progress) +{ + if (!from.hasImage() || !to.hasImage()) + return to; + + // FIXME (74112): Support transitioning between NinePieceImages that differ by more than image content. + + if (from.imageSlices() != to.imageSlices() || from.borderSlices() != to.borderSlices() || from.outset() != to.outset() || from.fill() != to.fill() || from.horizontalRule() != to.horizontalRule() || from.verticalRule() != to.verticalRule()) + return to; + + if (from.image()->imageSize(anim->renderer(), 1.0) != to.image()->imageSize(anim->renderer(), 1.0)) + return to; + + RefPtr<StyleImage> newContentImage = blendFunc(anim, from.image(), to.image(), progress); + + return NinePieceImage(newContentImage, from.imageSlices(), from.fill(), from.borderSlices(), from.outset(), from.horizontalRule(), from.verticalRule()); +} + class PropertyWrapperBase; static void addShorthandProperties(); @@ -295,6 +353,24 @@ protected: void (RenderStyle::*m_setter)(T); }; +template <typename T> +class RefCountedPropertyWrapper : public PropertyWrapperGetter<T*> { +public: + RefCountedPropertyWrapper(int prop, T* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<T>)) + : PropertyWrapperGetter<T*>(prop, getter) + , m_setter(setter) + { + } + + virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const + { + (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T*>::m_getter)(), (b->*PropertyWrapperGetter<T*>::m_getter)(), progress)); + } + +protected: + void (RenderStyle::*m_setter)(PassRefPtr<T>); +}; + #if USE(ACCELERATED_COMPOSITING) class PropertyWrapperAcceleratedOpacity : public PropertyWrapper<float> { public: @@ -568,6 +644,24 @@ protected: void (FillLayer::*m_setter)(T); }; +template <typename T> +class FillLayerRefCountedPropertyWrapper : public FillLayerPropertyWrapperGetter<T*> { +public: + FillLayerRefCountedPropertyWrapper(T* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<T>)) + : FillLayerPropertyWrapperGetter<T*>(getter) + , m_setter(setter) + { + } + + virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const + { + (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), progress)); + } + +protected: + void (FillLayer::*m_setter)(PassRefPtr<T>); +}; + class FillLayersPropertyWrapper : public PropertyWrapperBase { public: @@ -593,6 +687,9 @@ public: case CSSPropertyWebkitMaskSize: m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<LengthSize>(&FillLayer::sizeLength, &FillLayer::setSizeLength); break; + case CSSPropertyBackgroundImage: + m_fillLayerPropertyWrapper = new FillLayerRefCountedPropertyWrapper<StyleImage>(&FillLayer::image, &FillLayer::setImage); + break; } } @@ -774,6 +871,16 @@ void AnimationBase::ensurePropertyMap() gPropertyWrappers->append(new PropertyWrapper<const Color&>(CSSPropertyBackgroundColor, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor)); + gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundImage, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); + gPropertyWrappers->append(new RefCountedPropertyWrapper<StyleImage>(CSSPropertyListStyleImage, &RenderStyle::listStyleImage, &RenderStyle::setListStyleImage)); + gPropertyWrappers->append(new RefCountedPropertyWrapper<StyleImage>(CSSPropertyWebkitMaskImage, &RenderStyle::maskImage, &RenderStyle::setMaskImage)); + + gPropertyWrappers->append(new RefCountedPropertyWrapper<StyleImage>(CSSPropertyBorderImageSource, &RenderStyle::borderImageSource, &RenderStyle::setBorderImageSource)); + gPropertyWrappers->append(new PropertyWrapper<const NinePieceImage&>(CSSPropertyBorderImage, &RenderStyle::borderImage, &RenderStyle::setBorderImage)); + + gPropertyWrappers->append(new RefCountedPropertyWrapper<StyleImage>(CSSPropertyWebkitMaskBoxImageSource, &RenderStyle::maskBoxImageSource, &RenderStyle::setMaskBoxImageSource)); + gPropertyWrappers->append(new PropertyWrapper<const NinePieceImage&>(CSSPropertyWebkitMaskBoxImage, &RenderStyle::maskBoxImage, &RenderStyle::setMaskBoxImage)); + gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionX, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionY, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); @@ -896,10 +1003,10 @@ static void addPropertyWrapper(int propertyID, PropertyWrapperBase* wrapper) static void addShorthandProperties() { static const int animatableShorthandProperties[] = { - CSSPropertyBackground, // for background-color, background-position + CSSPropertyBackground, // for background-color, background-position, background-image CSSPropertyBackgroundPosition, CSSPropertyFont, // for font-size, font-weight - CSSPropertyWebkitMask, // for mask-position + CSSPropertyWebkitMask, // for mask-position CSSPropertyWebkitMaskPosition, CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft, CSSPropertyBorderColor, @@ -907,6 +1014,7 @@ static void addShorthandProperties() CSSPropertyBorderWidth, CSSPropertyBorder, CSSPropertyBorderSpacing, + CSSPropertyListStyle, // for list-style-image CSSPropertyMargin, CSSPropertyOutline, CSSPropertyPadding, diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.cpp b/third_party/WebKit/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.cpp index 03e5fc2..f8d3d77 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.cpp +++ b/third_party/WebKit/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.cpp @@ -43,7 +43,7 @@ CrossfadeGeneratedImage::CrossfadeGeneratedImage(Image* fromImage, Image* toImag m_size = size; } -void CrossfadeGeneratedImage::drawCrossfade(GraphicsContext* context, const FloatRect& srcRect) +void CrossfadeGeneratedImage::drawCrossfade(GraphicsContext* context) { float inversePercentage = 1 - m_percentage; @@ -64,8 +64,6 @@ void CrossfadeGeneratedImage::drawCrossfade(GraphicsContext* context, const Floa if (m_crossfadeSize != fromImageSize) context->scale(FloatSize(static_cast<float>(m_crossfadeSize.width()) / fromImageSize.width(), static_cast<float>(m_crossfadeSize.height()) / fromImageSize.height())); - context->translate(-srcRect.x() * fromImageSize.width() / static_cast<float>(m_crossfadeSize.width()), - -srcRect.y() * fromImageSize.height() / static_cast<float>(m_crossfadeSize.height())); context->setAlpha(inversePercentage); context->drawImage(m_fromImage, ColorSpaceDeviceRGB, IntPoint()); context->restore(); @@ -75,8 +73,6 @@ void CrossfadeGeneratedImage::drawCrossfade(GraphicsContext* context, const Floa if (m_crossfadeSize != toImageSize) context->scale(FloatSize(static_cast<float>(m_crossfadeSize.width()) / toImageSize.width(), static_cast<float>(m_crossfadeSize.height()) / toImageSize.height())); - context->translate(-srcRect.x() * toImageSize.width() / static_cast<float>(m_crossfadeSize.width()), - -srcRect.y() * toImageSize.height() / static_cast<float>(m_crossfadeSize.height())); context->setAlpha(m_percentage); context->drawImage(m_toImage, ColorSpaceDeviceRGB, IntPoint(), CompositePlusLighter); context->restore(); @@ -86,16 +82,18 @@ void CrossfadeGeneratedImage::drawCrossfade(GraphicsContext* context, const Floa void CrossfadeGeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp) { - UNUSED_PARAM(compositeOp); - GraphicsContextStateSaver stateSaver(*context); + context->setCompositeOperation(compositeOp); context->clip(dstRect); context->translate(dstRect.x(), dstRect.y()); + if (dstRect.size() != srcRect.size()) + context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height())); + context->translate(-srcRect.x(), -srcRect.y()); - drawCrossfade(context, srcRect); + drawCrossfade(context); } -void CrossfadeGeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& destRect) +void CrossfadeGeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& dstRect) { OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(m_size); if (!imageBuffer) @@ -103,10 +101,10 @@ void CrossfadeGeneratedImage::drawPattern(GraphicsContext* context, const FloatR // Fill with the cross-faded image. GraphicsContext* graphicsContext = imageBuffer->context(); - drawCrossfade(graphicsContext, FloatRect(FloatPoint(), m_crossfadeSize)); + drawCrossfade(graphicsContext); // Tile the image buffer into the context. - imageBuffer->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect); + imageBuffer->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, compositeOp, dstRect); } } diff --git a/third_party/WebKit/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h b/third_party/WebKit/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h index 557e3b9..ade2e5b 100644 --- a/third_party/WebKit/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h +++ b/third_party/WebKit/Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h @@ -45,12 +45,12 @@ public: protected: virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); - virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); + virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& dstRect); CrossfadeGeneratedImage(Image* fromImage, Image* toImage, float percentage, IntSize crossfadeSize, const IntSize&); private: - void drawCrossfade(GraphicsContext*, const FloatRect& srcRect); + void drawCrossfade(GraphicsContext*); Image* m_fromImage; Image* m_toImage; diff --git a/third_party/WebKit/Source/WebCore/rendering/style/RenderStyle.h b/third_party/WebKit/Source/WebCore/rendering/style/RenderStyle.h index ba62d91..123c1fb 100644 --- a/third_party/WebKit/Source/WebCore/rendering/style/RenderStyle.h +++ b/third_party/WebKit/Source/WebCore/rendering/style/RenderStyle.h @@ -1056,6 +1056,8 @@ public: } } + void setMaskImage(PassRefPtr<StyleImage> v) { rareNonInheritedData.access()->m_mask.setImage(v); } + void setMaskBoxImage(const NinePieceImage& b) { SET_VAR(rareNonInheritedData, m_maskBoxImage, b) } void setMaskBoxImageSource(PassRefPtr<StyleImage> v) { rareNonInheritedData.access()->m_maskBoxImage.setImage(v); } void setMaskXPosition(Length l) { SET_VAR(rareNonInheritedData, m_mask.m_xPosition, l) } |