Implement reverse animation direction
https://bugs.webkit.org/show_bug.cgi?id=60525
Implement reverse and alternate-reverse direction.
Reviewed by Dean Jackson.
Tests: animations/animation-direction-alternate-reverse.html
animations/animation-direction-reverse.html
animations/fill-mode-reverse.html
* css/CSSParser.cpp:
(WebCore::CSSParser::parseAnimationDirection):
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::mapAnimationDirection):
* css/CSSValueKeywords.in:
* page/WebKitAnimation.cpp:
(WebCore::WebKitAnimation::direction):
* page/WebKitAnimation.h:
* page/animation/AnimationBase.cpp:
(WebCore::AnimationBase::fractionalTime):
* platform/animation/Animation.h:
(Animation):
* platform/graphics/texmap/TextureMapperAnimation.cpp:
(WebCore):
(WebCore::shouldReverseAnimationValue):
(WebCore::normalizedAnimationValue):
LayoutTests: Implement reverse animation direction
https://bugs.webkit.org/show_bug.cgi?id=60525
Add test for the new animation-direction values.
Reviewed by Dean Jackson.
* animations/animation-direction-alternate-reverse-expected.txt: Added.
* animations/animation-direction-alternate-reverse.html: Added.
* animations/animation-direction-reverse-expected.txt: Added.
* animations/animation-direction-reverse.html: Added.
* animations/fill-mode-reverse-expected.txt: Added.
* animations/fill-mode-reverse.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@107162
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-02-08 Igor Oliveira <igor.o@sisa.samsung.com>
+
+ Implement reverse animation direction
+ https://bugs.webkit.org/show_bug.cgi?id=60525
+
+ Add test for the new animation-direction values.
+
+ Reviewed by Dean Jackson.
+
+ * animations/animation-direction-alternate-reverse-expected.txt: Added.
+ * animations/animation-direction-alternate-reverse.html: Added.
+ * animations/animation-direction-reverse-expected.txt: Added.
+ * animations/animation-direction-reverse.html: Added.
+ * animations/fill-mode-reverse-expected.txt: Added.
+ * animations/fill-mode-reverse.html: Added.
+
2012-02-08 David Hyatt <hyatt@apple.com>
https://bugs.webkit.org/show_bug.cgi?id=78157
--- /dev/null
+PASS - "left" property for "box" element at 1s saw something close to: 200
+PASS - "left" property for "box" element at 2s saw something close to: 0
+PASS - "left" property for "box" element at 3s saw something close to: 200
+PASS - "left" property for "box" element at 4s saw something close to: 400
+
--- /dev/null
+<!DOCTYPE html>
+
+<html>
+<head>
+ <style type="text/css" media="screen">
+
+ #container {
+ position: relative;
+ border: 1px solid black;
+ height: 100px;
+ width: 500px;
+ }
+
+ #box {
+ position: absolute;
+ height: 100px;
+ width: 100px;
+ background-color: blue;
+ -webkit-animation-name: move;
+ -webkit-animation-duration: 2s;
+ -webkit-animation-direction: alternate-reverse;
+ -webkit-animation-iteration-count: 2;
+ -webkit-animation-timing-function: linear;
+ }
+
+ @-webkit-keyframes move {
+ 0% {
+ left: 0;
+ }
+ 100% {
+ left: 400px;
+ }
+ }
+
+ </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]
+ ["move", 1.0, "box", "left", 200, 20],
+ ["move", 2.0, "box", "left", 0, 20],
+
+ ["move", 3.0, "box", "left", 200, 20],
+ ["move", 4.0, "box", "left", 400, 20],
+ ];
+
+ runAnimationTest(expectedValues);
+ </script>
+</head>
+<body>
+
+<!-- Test animation-direction: alternate-reverse -->
+<div id="container">
+ <div id="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
--- /dev/null
+PASS - "webkitTransform" property for "box" element at 0.5s saw something close to: 1,0,0,1,150,0
+PASS - "webkitTransform" property for "box" element at 1s saw something close to: 1,0,0,1,100,0
+PASS - "webkitTransform" property for "box" element at 2.5s saw something close to: 1,0,0,1,200,0
+
--- /dev/null
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Test of -webkit-animation-play-state</title>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ }
+
+ #box {
+ position: absolute;
+ left: 0px;
+ top: 100px;
+ height: 100px;
+ width: 100px;
+ background-color: red;
+ margin: 0;
+ -webkit-animation-duration: 2s;
+ -webkit-animation-direction: reverse;
+ -webkit-animation-timing-function: linear;
+ -webkit-animation-name: "move1";
+ }
+ @-webkit-keyframes "move1" {
+ from { -webkit-transform: translateX(0px); }
+ to { -webkit-transform: translateX(200px); }
+ }
+ #result {
+ color: white; /* hide from pixel results */
+ }
+ </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]
+ ["move1", 0.5, "box", "webkitTransform", [1,0,0,1, 150,0], 20],
+ ["move1", 1.0, "box", "webkitTransform", [1,0,0,1,100,0], 20],
+ ["move1", 2.5, "box", "webkitTransform", [1,0,0,1, 200,0], 20],
+ ];
+
+ function pauseAnimation()
+ {
+ document.getElementById("box").style.webkitAnimationPlayState = "paused";
+ }
+
+ function setTimers()
+ {
+ setTimeout(pauseAnimation, 2500);
+ }
+
+ runAnimationTest(expectedValues, setTimers, null, true);
+
+ </script>
+</head>
+<body>
+<div id="box"></div>
+<div id="result"></div>
+</div>
+</body>
+</html>
--- /dev/null
+This test performs an animation of the left property with four different fill modes. It animates over 0.1 second with a 0.1 second delay. It takes snapshots at document load and the end of the animation.
+None
+Backwards
+Forwards
+Both
+Both iterating
+PASS - start of animation - id: a expected: 100 actual: 100
+PASS - start of animation - id: b expected: 300 actual: 300
+PASS - start of animation - id: c expected: 100 actual: 100
+PASS - start of animation - id: d expected: 300 actual: 300
+PASS - start of animation - id: e expected: 200 actual: 200
+PASS - end of animation - id: a expected: 100 actual: 100
+PASS - end of animation - id: b expected: 100 actual: 100
+PASS - end of animation - id: c expected: 300 actual: 300
+PASS - end of animation - id: d expected: 300 actual: 300
+PASS - end of animation - id: e expected: 200 actual: 200
+
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Test simple animation with fill modes</title>
+ <style type="text/css" media="screen">
+ .box {
+ position: relative;
+ left: 100px;
+ top: 10px;
+ height: 100px;
+ width: 100px;
+ -webkit-animation-delay: 0.1s;
+ -webkit-animation-duration: 2s;
+ -webkit-animation-timing-function: linear;
+ -webkit-animation-name: anim;
+ -webkit-animation-direction: reverse
+ }
+ @-webkit-keyframes anim {
+ from { left: 200px; }
+ to { left: 300px; }
+ }
+ #a {
+ background-color: blue;
+ -webkit-animation-fill-mode: none;
+ }
+ #b {
+ background-color: red;
+ -webkit-animation-fill-mode: backwards;
+ }
+ #c {
+ background-color: green;
+ -webkit-animation-fill-mode: forwards;
+ }
+ #d {
+ background-color: yellow;
+ -webkit-animation-fill-mode: both;
+ }
+ #e {
+ background-color: #999;
+ -webkit-animation-fill-mode: both;
+ -webkit-animation-iteration-count: 2;
+ -webkit-animation-direction: alternate;
+ }
+ </style>
+ <script type="text/javascript" charset="utf-8">
+ const numAnims = 5;
+ var animsFinished = 0;
+ const allowance = 5;
+ const expectedValues = [
+ {id: "a", start: 100, end: 100},
+ {id: "b", start: 300, end: 100},
+ {id: "c", start: 100, end: 300},
+ {id: "d", start: 300, end: 300},
+ {id: "e", start: 200, end: 200}
+ ];
+ var result = "";
+
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+ }
+
+ function animationEnded(event) {
+ if (++animsFinished == numAnims) {
+ setTimeout(endTest, 0); // this set timeout should be ok in the test environment
+ // since we're just giving style a chance to resolve
+ }
+ };
+
+ function endTest() {
+
+ for (var i=0; i < expectedValues.length; i++) {
+ var el = document.getElementById(expectedValues[i].id);
+ var expectedValue = expectedValues[i].end;
+ var realValue = window.getComputedStyle(el).getPropertyCSSValue("left").getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+ if (Math.abs(expectedValue - realValue) < allowance) {
+ result += "PASS";
+ } else {
+ result += "FAIL";
+ }
+ result += " - end of animation - id: " + expectedValues[i].id + " expected: " + expectedValue + " actual: " + realValue + "<br>";
+ }
+ document.getElementById('result').innerHTML = result;
+
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+ }
+
+ window.onload = function () {
+ for (var i=0; i < expectedValues.length; i++) {
+ var el = document.getElementById(expectedValues[i].id);
+ var expectedValue = expectedValues[i].start;
+ var realValue = window.getComputedStyle(el).getPropertyCSSValue("left").getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+ if (Math.abs(expectedValue - realValue) < allowance) {
+ result += "PASS";
+ } else {
+ result += "FAIL";
+ }
+ result += " - start of animation - id: " + expectedValues[i].id + " expected: " + expectedValue + " actual: " + realValue + "<br>";
+ }
+ document.addEventListener("webkitAnimationEnd", animationEnded, false);
+ };
+
+ </script>
+</head>
+<body>
+This test performs an animation of the left property with four different
+fill modes. It animates over 0.1 second with a 0.1 second delay.
+It takes snapshots at document load and the end of the animation.
+<div id="a" class="box">
+ None
+</div>
+<div id="b" class="box">
+ Backwards
+</div>
+<div id="c" class="box">
+ Forwards
+</div>
+<div id="d" class="box">
+ Both
+</div>
+<div id="e" class="box">
+ Both iterating
+</div>
+<div id="result">
+</div>
+</body>
+</html>
+2012-02-08 Igor Oliveira <igor.o@sisa.samsung.com>
+
+ Implement reverse animation direction
+
+ Implement reverse animation direction
+ https://bugs.webkit.org/show_bug.cgi?id=60525
+
+ Implement reverse and alternate-reverse direction.
+
+ Reviewed by Dean Jackson.
+
+ Tests: animations/animation-direction-alternate-reverse.html
+ animations/animation-direction-reverse.html
+ animations/fill-mode-reverse.html
+
+ * css/CSSParser.cpp:
+ (WebCore::CSSParser::parseAnimationDirection):
+ * css/CSSStyleSelector.cpp:
+ (WebCore::CSSStyleSelector::mapAnimationDirection):
+ * css/CSSValueKeywords.in:
+ * page/WebKitAnimation.cpp:
+ (WebCore::WebKitAnimation::direction):
+ * page/WebKitAnimation.h:
+ * page/animation/AnimationBase.cpp:
+ (WebCore::AnimationBase::fractionalTime):
+ * platform/animation/Animation.h:
+ (Animation):
+ * platform/graphics/texmap/TextureMapperAnimation.cpp:
+ (WebCore):
+ (WebCore::shouldReverseAnimationValue):
+ (WebCore::normalizedAnimationValue):
+
2012-02-08 James Robinson <jamesr@chromium.org>
[chromium] Avoid creating a temporary GraphicsContext3D if someone requests the WebView's GraphicsContext3D before initialization is complete
PassRefPtr<CSSValue> CSSParser::parseAnimationDirection()
{
CSSParserValue* value = m_valueList->current();
- if (value->id == CSSValueNormal || value->id == CSSValueAlternate)
+ if (value->id == CSSValueNormal || value->id == CSSValueAlternate || value->id == CSSValueReverse || value->id == CSSValueAlternateReverse)
return cssValuePool()->createIdentifierValue(value->id);
return 0;
}
return;
CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- layer->setDirection(primitiveValue->getIdent() == CSSValueAlternate ? Animation::AnimationDirectionAlternate : Animation::AnimationDirectionNormal);
+ switch (primitiveValue->getIdent()) {
+ case CSSValueNormal:
+ layer->setDirection(Animation::AnimationDirectionNormal);
+ break;
+ case CSSValueAlternate:
+ layer->setDirection(Animation::AnimationDirectionAlternate);
+ break;
+ case CSSValueReverse:
+ layer->setDirection(Animation::AnimationDirectionReverse);
+ break;
+ case CSSValueAlternateReverse:
+ layer->setDirection(Animation::AnimationDirectionAlternateReverse);
+ break;
+ }
}
void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* value)
//
// alternate
+alternate-reverse
+
//
// CSS_PROP__WEBKIT_ANIMATION_FILL_MODE
//
WebKitAnimation::Direction WebKitAnimation::direction() const
{
- if (m_keyframeAnimation->animation()->direction() == Animation::AnimationDirectionNormal)
+ switch (m_keyframeAnimation->animation()->direction()) {
+ case Animation::AnimationDirectionNormal:
return DIRECTION_NORMAL;
- return DIRECTION_ALTERNATE;
+ case Animation::AnimationDirectionAlternate:
+ return DIRECTION_ALTERNATE;
+ case Animation::AnimationDirectionReverse:
+ return DIRECTION_REVERSE;
+ case Animation::AnimationDirectionAlternateReverse:
+ return DIRECTION_ALTERNATE_REVERSE;
+ }
+ ASSERT_NOT_REACHED();
+ return DIRECTION_NORMAL;
}
WebKitAnimation::FillMode WebKitAnimation::fillMode() const
bool ended() const;
// direction
- enum Direction { DIRECTION_NORMAL, DIRECTION_ALTERNATE };
+ enum Direction { DIRECTION_NORMAL, DIRECTION_ALTERNATE, DIRECTION_REVERSE, DIRECTION_ALTERNATE_REVERSE };
Direction direction() const;
// fill mode
integralTime = min(integralTime, m_animation->iterationCount() - 1);
fractionalTime -= integralTime;
- if ((m_animation->direction() == Animation::AnimationDirectionAlternate) && (integralTime & 1))
+ if (((m_animation->direction() == Animation::AnimationDirectionAlternate) && (integralTime & 1))
+ || ((m_animation->direction() == Animation::AnimationDirectionAlternateReverse) && !(integralTime & 1))
+ || m_animation->direction() == Animation::AnimationDirectionReverse)
fractionalTime = 1 - fractionalTime;
if (scale != 1 || offset)
static PassRefPtr<Animation> create() { return adoptRef(new Animation); }
static PassRefPtr<Animation> create(const Animation* o) { return adoptRef(new Animation(*o)); }
-
+
bool isDelaySet() const { return m_delaySet; }
bool isDirectionSet() const { return m_directionSet; }
bool isDurationSet() const { return m_durationSet; }
double delay() const { return m_delay; }
- enum AnimationDirection { AnimationDirectionNormal, AnimationDirectionAlternate };
+ enum AnimationDirection {
+ AnimationDirectionNormal,
+ AnimationDirectionAlternate,
+ AnimationDirectionReverse,
+ AnimationDirectionAlternateReverse
+ };
AnimationDirection direction() const { return static_cast<AnimationDirection>(m_direction); }
unsigned fillMode() const { return m_fillMode; }
double m_delay;
double m_duration;
RefPtr<TimingFunction> m_timingFunction;
- unsigned m_direction : 1; // AnimationDirection
+ unsigned m_direction : 2; // AnimationDirection
unsigned m_fillMode : 2;
unsigned m_playState : 2;
#if USE(TEXTURE_MAPPER)
namespace WebCore {
-static double normalizedAnimationValue(double runningTime, double duration, bool alternate)
+
+static bool shouldReverseAnimationValue(Animation::AnimationDirection direction, int loopCount)
+{
+ if (((direction == Animation::AnimationDirectionAlternate) && (loopCount & 1))
+ || ((direction == Animation::AnimationDirectionAlternateReverse) && !(loopCount & 1))
+ || direction == Animation::AnimationDirectionReverse)
+ return true;
+ return false;
+}
+
+static double normalizedAnimationValue(double runningTime, double duration, Animation::AnimationDirection direction)
{
if (!duration)
return 0;
const double lastFullLoop = duration * double(loopCount);
const double remainder = runningTime - lastFullLoop;
const double normalized = remainder / duration;
- return (loopCount % 2 && alternate) ? (1 - normalized) : normalized;
+
+ return shouldReverseAnimationValue(direction, loopCount) ? 1 - normalized : normalized;
}
static float applyOpacityAnimation(float fromOpacity, float toOpacity, double progress)