Parsing and Style Resolution of Container-based Animation Triggers
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 Mar 2015 00:33:00 +0000 (00:33 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 Mar 2015 00:33:00 +0000 (00:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=142687
<rdar://problem/20170007>

Reviewed by Simon Fraser.

Source/WebCore:

Take 2 after the previous patch was rolled out.

This is the beginning of a prototype implementation of
CSS Animation Triggers, as described by
https://lists.w3.org/Archives/Public/www-style/2014Sep/0135.html

In this patch we parse and resolve the value of a new
CSS property "-webkit-animation-trigger". At the moment it
only accepts one function value "container-scroll", which
will trigger the animation at an absolute position within
an element's scrolling container. We expect the syntax to
change in the near future, as the spec is written.

Tests: animations/trigger-computed-style.html
       animations/trigger-parsing.html

* WebCore.xcodeproj/project.pbxproj: Add the new files.

* css/CSSAnimationTriggerScrollValue.cpp: Added.
(WebCore::CSSAnimationTriggerScrollValue::customCSSText): Output text for computed style.
(WebCore::CSSAnimationTriggerScrollValue::equals): Compare two values.
* css/CSSAnimationTriggerScrollValue.h: Added. This holds the CSS side of the
scroll trigger. This name may change in the future to better represent the
type of trigger, but it is good enough for now.
(WebCore::CSSAnimationTriggerScrollValue::create):
(WebCore::CSSAnimationTriggerScrollValue::startValue):
(WebCore::CSSAnimationTriggerScrollValue::endValue):
(WebCore::CSSAnimationTriggerScrollValue::CSSAnimationTriggerScrollValue):

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::createAnimationTriggerValue): Maps an AnimationTrigger into a CSSValue.
(WebCore::getAnimationTriggerValue): Gets the current computed style.
(WebCore::ComputedStyleExtractor::propertyValue):

* css/CSSParser.cpp:
(WebCore::CSSParser::parseValue):
(WebCore::CSSParser::parseAnimationTrigger): Parse the "container-scroll" function
and record the value as a CSSAnimationTriggerScrollValue.
(WebCore::CSSParser::parseAnimationProperty): Handle the new property.
* css/CSSParser.h:

* css/CSSPropertyNames.in: Add "-webkit-animation-trigger".

* css/CSSToStyleMap.cpp:
(WebCore::CSSToStyleMap::mapAnimationTrigger): Map a CSSValue into a trigger value on
an Animation object.
* css/CSSToStyleMap.h:

* css/CSSValue.cpp: Handle the new CSSValue type.
(WebCore::CSSValue::equals):
(WebCore::CSSValue::cssText):
(WebCore::CSSValue::destroy):
* css/CSSValue.h:
(WebCore::CSSValue::isAnimationTriggerScrollValue):

* platform/animation/Animation.cpp: Make sure to initialise m_trigger and m_triggerSet,
and use them in the operator==.
* platform/animation/Animation.h: Add AnimationTrigger as a new field.
(WebCore::Animation::isTriggerSet):
(WebCore::Animation::isEmpty):

* platform/animation/AnimationTrigger.h: Added. New base class and subclasses for
"auto" and the scrolling trigger.
(WebCore::AnimationTrigger::~AnimationTrigger):
(WebCore::AnimationTrigger::type):
(WebCore::AnimationTrigger::isAutoAnimationTrigger):
(WebCore::AnimationTrigger::isScrollAnimationTrigger):
(WebCore::AnimationTrigger::AnimationTrigger):
(WebCore::AutoAnimationTrigger::create):
(WebCore::AutoAnimationTrigger::~AutoAnimationTrigger):
(WebCore::AutoAnimationTrigger::AutoAnimationTrigger):
(WebCore::ScrollAnimationTrigger::create):
(WebCore::ScrollAnimationTrigger::~ScrollAnimationTrigger):
(WebCore::ScrollAnimationTrigger::startValue):
(WebCore::ScrollAnimationTrigger::setStartValue):
(WebCore::ScrollAnimationTrigger::endValue):
(WebCore::ScrollAnimationTrigger::setEndValue):
(WebCore::ScrollAnimationTrigger::hasEndValue):
(WebCore::ScrollAnimationTrigger::setHasEndValue):
(WebCore::ScrollAnimationTrigger::ScrollAnimationTrigger):

LayoutTests:

Take 2.

New tests that exercise the parser and computed style
of -webkit-animation-trigger.

* animations/script-tests/trigger-computed-style.js: Added.
(testComputedTriggerRule):
* animations/script-tests/trigger-parsing.js: Added.
(testTriggerRule):
* animations/trigger-computed-style-expected.txt: Added.
* animations/trigger-computed-style.html: Added.
* animations/trigger-parsing-expected.txt: Added.
* animations/trigger-parsing.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181602 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/animations/script-tests/trigger-computed-style.js [new file with mode: 0644]
LayoutTests/animations/script-tests/trigger-parsing.js [new file with mode: 0644]
LayoutTests/animations/trigger-computed-style-expected.txt [new file with mode: 0644]
LayoutTests/animations/trigger-computed-style.html [new file with mode: 0644]
LayoutTests/animations/trigger-parsing-expected.txt [new file with mode: 0644]
LayoutTests/animations/trigger-parsing.html [new file with mode: 0644]
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/win/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSAnimationTriggerScrollValue.cpp [new file with mode: 0644]
Source/WebCore/css/CSSAnimationTriggerScrollValue.h [new file with mode: 0644]
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSParser.h
Source/WebCore/css/CSSPropertyNames.in
Source/WebCore/css/CSSToStyleMap.cpp
Source/WebCore/css/CSSToStyleMap.h
Source/WebCore/css/CSSValue.cpp
Source/WebCore/css/CSSValue.h
Source/WebCore/platform/animation/Animation.cpp
Source/WebCore/platform/animation/Animation.h
Source/WebCore/platform/animation/AnimationTrigger.h [new file with mode: 0644]

index 73993f2..bbe02e7 100644 (file)
@@ -1,3 +1,25 @@
+2015-03-16  Dean Jackson  <dino@apple.com>
+
+        Parsing and Style Resolution of Container-based Animation Triggers
+        https://bugs.webkit.org/show_bug.cgi?id=142687
+        <rdar://problem/20170007>
+
+        Reviewed by Simon Fraser.
+
+        Take 2.
+
+        New tests that exercise the parser and computed style
+        of -webkit-animation-trigger.
+
+        * animations/script-tests/trigger-computed-style.js: Added.
+        (testComputedTriggerRule):
+        * animations/script-tests/trigger-parsing.js: Added.
+        (testTriggerRule):
+        * animations/trigger-computed-style-expected.txt: Added.
+        * animations/trigger-computed-style.html: Added.
+        * animations/trigger-parsing-expected.txt: Added.
+        * animations/trigger-parsing.html: Added.
+
 2015-03-16  Joanmarie Diggs  <jdiggs@igalia.com>
 
         AX: Crash viewing http://www.last.fm/
diff --git a/LayoutTests/animations/script-tests/trigger-computed-style.js b/LayoutTests/animations/script-tests/trigger-computed-style.js
new file mode 100644 (file)
index 0000000..108b1c1
--- /dev/null
@@ -0,0 +1,65 @@
+description("Test the computed style of the -webkit-animation-trigger property.");
+
+// These have to be global for the test helpers to see them.
+var stylesheet, triggerStyle, subRule;
+var styleElement = document.createElement("style");
+document.head.appendChild(styleElement);
+stylesheet = styleElement.sheet;
+
+function testComputedTriggerRule(description, rule, expectedLength, expectedTexts)
+{
+    debug("");
+    debug(description + " : " + rule);
+
+    stylesheet.insertRule("body { -webkit-animation-trigger: " + rule + "; }", 0);
+
+    triggerStyle = window.getComputedStyle(document.body).getPropertyCSSValue("-webkit-animation-trigger");
+    shouldBe("triggerStyle.length", "" + expectedLength);
+    for (var i = 0; i < expectedLength; i++) {
+        subRule = triggerStyle[i];
+        shouldBe("subRule.cssText", "'" + expectedTexts[i] + "'");
+    }
+    stylesheet.deleteRule(0);
+}
+
+testComputedTriggerRule("Auto",
+                        "auto", 1,
+                        ["auto"]);
+
+testComputedTriggerRule("One container-scroll value",
+                        "container-scroll(10px)", 1,
+                        ["container-scroll(10px)"]);
+
+testComputedTriggerRule("One container-scroll value",
+                        "container-scroll(2em)", 1,
+                        ["container-scroll(32px)"]);
+
+testComputedTriggerRule("One container-scroll value with end value",
+                        "container-scroll(10px, 20px)", 1,
+                        ["container-scroll(10px, 20px)"]);
+
+testComputedTriggerRule("Two container-scroll values",
+                        "container-scroll(10px), container-scroll(20px)", 2,
+                        ["container-scroll(10px)", "container-scroll(20px)"]);
+
+testComputedTriggerRule("Many container-scroll values",
+                        "container-scroll(10px), container-scroll(20px), container-scroll(30px), container-scroll(40px), container-scroll(1px)", 5,
+                        ["container-scroll(10px)", "container-scroll(20px)", "container-scroll(30px)", "container-scroll(40px)", "container-scroll(1px)"]);
+
+testComputedTriggerRule("No value",
+                        "", 1,
+                        ["auto"]);
+
+testComputedTriggerRule("Bad value",
+                        "banana", 1,
+                        ["auto"]);
+
+testComputedTriggerRule("Multiple bad values",
+                        "banana, eggs, bacon", 1,
+                        ["auto"]);
+
+testComputedTriggerRule("Some good, some bad values",
+                        "container-scroll(10), eggs, bacon", 1,
+                        ["auto"]);
+
+successfullyParsed = true;
diff --git a/LayoutTests/animations/script-tests/trigger-parsing.js b/LayoutTests/animations/script-tests/trigger-parsing.js
new file mode 100644 (file)
index 0000000..bddfbba
--- /dev/null
@@ -0,0 +1,80 @@
+description("Test the parsing of the -webkit-animation-trigger property.");
+
+// These have to be global for the test helpers to see them.
+var stylesheet, cssRule, declaration, triggerRule, subRule;
+var styleElement = document.createElement("style");
+document.head.appendChild(styleElement);
+stylesheet = styleElement.sheet;
+
+function testTriggerRule(description, rule, expectedLength, expectedValue, expectedTexts)
+{
+    debug("");
+    debug(description + " : " + rule);
+
+    stylesheet.insertRule("body { -webkit-animation-trigger: " + rule + "; }", 0);
+    cssRule = stylesheet.cssRules.item(0);
+
+    shouldBe("cssRule.type", "1");
+
+    declaration = cssRule.style;
+    if (!expectedLength || !expectedValue) {
+        shouldBe("declaration.length", "0");
+        shouldBe("declaration.getPropertyValue('-webkit-animation-trigger')", "null");
+        return;
+    }
+    shouldBe("declaration.length", "1");
+    shouldBe("declaration.getPropertyValue('-webkit-animation-trigger')", "'" + expectedValue + "'");
+
+    triggerRule = declaration.getPropertyCSSValue("-webkit-animation-trigger");
+    if (expectedLength > 1) {
+        shouldBe("triggerRule.length", "" + expectedLength);
+        for (var i = 0; i < expectedLength; i++) {
+            subRule = triggerRule[i];
+            shouldBe("subRule.cssText", "'" + expectedTexts[i] + "'");
+        }
+    } else {
+        shouldBe("triggerRule.cssText", "'" + expectedValue + "'");
+    }
+
+    stylesheet.deleteRule(0);
+}
+
+debug("")
+debug("Valid property tests");
+debug("")
+
+testTriggerRule("Auto",
+                "auto", 1, "auto");
+
+testTriggerRule("Container Scroll",
+                "container-scroll(200px)", 1, "container-scroll(200px)");
+
+testTriggerRule("Container Scroll",
+                "container-scroll(2em)", 1, "container-scroll(2em)");
+
+testTriggerRule("Container Scroll",
+                "container-scroll(30vw)", 1, "container-scroll(30vw)");
+
+testTriggerRule("Container Scroll with end value",
+                "container-scroll(200px, 300px)", 1, "container-scroll(200px, 300px)");
+
+testTriggerRule("Two scroll values",
+                "container-scroll(1px), container-scroll(2px)", 2, "container-scroll(1px), container-scroll(2px)", ["container-scroll(1px)", "container-scroll(2px)"]);
+
+testTriggerRule("Many scroll values",
+                "container-scroll(1px), container-scroll(2px), container-scroll(3px), container-scroll(4px), container-scroll(5px), container-scroll(3000px)",
+                6,
+                "container-scroll(1px), container-scroll(2px), container-scroll(3px), container-scroll(4px), container-scroll(5px), container-scroll(3000px)",
+                ["container-scroll(1px)", "container-scroll(2px)", "container-scroll(3px)", "container-scroll(4px)", "container-scroll(5px)", "container-scroll(3000px)"]);
+
+debug("")
+debug("Invalid property tests");
+debug("")
+
+testTriggerRule("No value", "", 0, null);
+testTriggerRule("Bad value", "banana", 0, null);
+testTriggerRule("Bad list", "container-scroll(1px), orange", 0, null);
+testTriggerRule("Missing comma", "container-scroll(1px) container-scroll(2px)", 0, null);
+testTriggerRule("Too many values", "container-scroll(1px, 2px, 3px)", 0, null);
+
+successfullyParsed = true;
diff --git a/LayoutTests/animations/trigger-computed-style-expected.txt b/LayoutTests/animations/trigger-computed-style-expected.txt
new file mode 100644 (file)
index 0000000..7b8af8c
--- /dev/null
@@ -0,0 +1,54 @@
+Test the computed style of the -webkit-animation-trigger property.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Auto : auto
+PASS triggerStyle.length is 1
+PASS subRule.cssText is 'auto'
+
+One container-scroll value : container-scroll(10px)
+PASS triggerStyle.length is 1
+PASS subRule.cssText is 'container-scroll(10px)'
+
+One container-scroll value : container-scroll(2em)
+PASS triggerStyle.length is 1
+PASS subRule.cssText is 'container-scroll(32px)'
+
+One container-scroll value with end value : container-scroll(10px, 20px)
+PASS triggerStyle.length is 1
+PASS subRule.cssText is 'container-scroll(10px, 20px)'
+
+Two container-scroll values : container-scroll(10px), container-scroll(20px)
+PASS triggerStyle.length is 2
+PASS subRule.cssText is 'container-scroll(10px)'
+PASS subRule.cssText is 'container-scroll(20px)'
+
+Many container-scroll values : container-scroll(10px), container-scroll(20px), container-scroll(30px), container-scroll(40px), container-scroll(1px)
+PASS triggerStyle.length is 5
+PASS subRule.cssText is 'container-scroll(10px)'
+PASS subRule.cssText is 'container-scroll(20px)'
+PASS subRule.cssText is 'container-scroll(30px)'
+PASS subRule.cssText is 'container-scroll(40px)'
+PASS subRule.cssText is 'container-scroll(1px)'
+
+No value : 
+PASS triggerStyle.length is 1
+PASS subRule.cssText is 'auto'
+
+Bad value : banana
+PASS triggerStyle.length is 1
+PASS subRule.cssText is 'auto'
+
+Multiple bad values : banana, eggs, bacon
+PASS triggerStyle.length is 1
+PASS subRule.cssText is 'auto'
+
+Some good, some bad values : container-scroll(10), eggs, bacon
+PASS triggerStyle.length is 1
+PASS subRule.cssText is 'auto'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/animations/trigger-computed-style.html b/LayoutTests/animations/trigger-computed-style.html
new file mode 100644 (file)
index 0000000..2951d56
--- /dev/null
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<script src="../resources/js-test-pre.js"></script>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/trigger-computed-style.js"></script>
+<script src="../resources/js-test-post.js"></script>
diff --git a/LayoutTests/animations/trigger-parsing-expected.txt b/LayoutTests/animations/trigger-parsing-expected.txt
new file mode 100644 (file)
index 0000000..e2f506c
--- /dev/null
@@ -0,0 +1,90 @@
+Test the parsing of the -webkit-animation-trigger property.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Valid property tests
+
+
+Auto : auto
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is 'auto'
+PASS triggerRule.cssText is 'auto'
+
+Container Scroll : container-scroll(200px)
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is 'container-scroll(200px)'
+PASS triggerRule.cssText is 'container-scroll(200px)'
+
+Container Scroll : container-scroll(2em)
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is 'container-scroll(2em)'
+PASS triggerRule.cssText is 'container-scroll(2em)'
+
+Container Scroll : container-scroll(30vw)
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is 'container-scroll(30vw)'
+PASS triggerRule.cssText is 'container-scroll(30vw)'
+
+Container Scroll with end value : container-scroll(200px, 300px)
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is 'container-scroll(200px, 300px)'
+PASS triggerRule.cssText is 'container-scroll(200px, 300px)'
+
+Two scroll values : container-scroll(1px), container-scroll(2px)
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is 'container-scroll(1px), container-scroll(2px)'
+PASS triggerRule.length is 2
+PASS subRule.cssText is 'container-scroll(1px)'
+PASS subRule.cssText is 'container-scroll(2px)'
+
+Many scroll values : container-scroll(1px), container-scroll(2px), container-scroll(3px), container-scroll(4px), container-scroll(5px), container-scroll(3000px)
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is 'container-scroll(1px), container-scroll(2px), container-scroll(3px), container-scroll(4px), container-scroll(5px), container-scroll(3000px)'
+PASS triggerRule.length is 6
+PASS subRule.cssText is 'container-scroll(1px)'
+PASS subRule.cssText is 'container-scroll(2px)'
+PASS subRule.cssText is 'container-scroll(3px)'
+PASS subRule.cssText is 'container-scroll(4px)'
+PASS subRule.cssText is 'container-scroll(5px)'
+PASS subRule.cssText is 'container-scroll(3000px)'
+
+Invalid property tests
+
+
+No value : 
+PASS cssRule.type is 1
+PASS declaration.length is 0
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is null
+
+Bad value : banana
+PASS cssRule.type is 1
+PASS declaration.length is 0
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is null
+
+Bad list : container-scroll(1px), orange
+PASS cssRule.type is 1
+PASS declaration.length is 0
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is null
+
+Missing comma : container-scroll(1px) container-scroll(2px)
+PASS cssRule.type is 1
+PASS declaration.length is 0
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is null
+
+Too many values : container-scroll(1px, 2px, 3px)
+PASS cssRule.type is 1
+PASS declaration.length is 0
+PASS declaration.getPropertyValue('-webkit-animation-trigger') is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/animations/trigger-parsing.html b/LayoutTests/animations/trigger-parsing.html
new file mode 100644 (file)
index 0000000..ccdff09
--- /dev/null
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<script src="../resources/js-test-pre.js"></script>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/trigger-parsing.js"></script>
+<script src="../resources/js-test-post.js"></script>
index 4e5e99d..78dcb07 100644 (file)
@@ -62,6 +62,10 @@ fast/dom/Window/slow-unload-handler-only-frame-is-stopped.html
 # Need a scroll snap point implementation
 css3/scroll-snap [ Skip ]
 
+# TODO Animation triggers not supported
+animations/trigger-computed-style.html [ Skip ]
+animations/trigger-parsing.html [ Skip ]
+
 # ----------------------------------------
 # Tests which also fail in other platforms
 # ----------------------------------------
index e61718d..54bd5d3 100644 (file)
@@ -460,6 +460,10 @@ Bug(GTK) fast/css/style-scoped [ Skip ]
 # ENABLE(CSS_SCROLL_SNAP) is disabled.
 css3/scroll-snap
 
+# TODO Animation triggers not supported
+animations/trigger-computed-style.html [ Skip ]
+animations/trigger-parsing.html [ Skip ]
+
 # ENABLE(SHADOW_DOM) is disabled.
 Bug(GTK) fast/dom/shadow [ Skip ]
 Bug(GTK) fast/dom/HTMLTemplateElement/cycles-in-shadow.html [ Skip ]
index 6a23d67..7f3ff28 100644 (file)
@@ -594,6 +594,11 @@ webkit.org/b/142260 fast/attachment [ Skip ]
 
 # TODO APNG is not supported
 webkit.org/b/142731 fast/images/animated-png.html [ Skip ]
+
+# TODO Animation triggers not supported
+animations/trigger-computed-style.html [ Skip ]
+animations/trigger-parsing.html [ Skip ]
+
 ################################################################################
 ###########    End Missing Functionality Prevents Testing         ##############
 ################################################################################
index 833bf14..1d77850 100644 (file)
@@ -1,3 +1,92 @@
+2015-03-16  Dean Jackson  <dino@apple.com>
+
+        Parsing and Style Resolution of Container-based Animation Triggers
+        https://bugs.webkit.org/show_bug.cgi?id=142687
+        <rdar://problem/20170007>
+
+        Reviewed by Simon Fraser.
+
+        Take 2 after the previous patch was rolled out.
+
+        This is the beginning of a prototype implementation of
+        CSS Animation Triggers, as described by
+        https://lists.w3.org/Archives/Public/www-style/2014Sep/0135.html
+
+        In this patch we parse and resolve the value of a new
+        CSS property "-webkit-animation-trigger". At the moment it
+        only accepts one function value "container-scroll", which
+        will trigger the animation at an absolute position within
+        an element's scrolling container. We expect the syntax to
+        change in the near future, as the spec is written.
+
+        Tests: animations/trigger-computed-style.html
+               animations/trigger-parsing.html
+
+        * WebCore.xcodeproj/project.pbxproj: Add the new files.
+
+        * css/CSSAnimationTriggerScrollValue.cpp: Added.
+        (WebCore::CSSAnimationTriggerScrollValue::customCSSText): Output text for computed style.
+        (WebCore::CSSAnimationTriggerScrollValue::equals): Compare two values.
+        * css/CSSAnimationTriggerScrollValue.h: Added. This holds the CSS side of the
+        scroll trigger. This name may change in the future to better represent the
+        type of trigger, but it is good enough for now.
+        (WebCore::CSSAnimationTriggerScrollValue::create):
+        (WebCore::CSSAnimationTriggerScrollValue::startValue):
+        (WebCore::CSSAnimationTriggerScrollValue::endValue):
+        (WebCore::CSSAnimationTriggerScrollValue::CSSAnimationTriggerScrollValue):
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::createAnimationTriggerValue): Maps an AnimationTrigger into a CSSValue.
+        (WebCore::getAnimationTriggerValue): Gets the current computed style.
+        (WebCore::ComputedStyleExtractor::propertyValue):
+
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::parseValue):
+        (WebCore::CSSParser::parseAnimationTrigger): Parse the "container-scroll" function
+        and record the value as a CSSAnimationTriggerScrollValue.
+        (WebCore::CSSParser::parseAnimationProperty): Handle the new property.
+        * css/CSSParser.h:
+
+        * css/CSSPropertyNames.in: Add "-webkit-animation-trigger".
+
+        * css/CSSToStyleMap.cpp:
+        (WebCore::CSSToStyleMap::mapAnimationTrigger): Map a CSSValue into a trigger value on
+        an Animation object.
+        * css/CSSToStyleMap.h:
+
+        * css/CSSValue.cpp: Handle the new CSSValue type.
+        (WebCore::CSSValue::equals):
+        (WebCore::CSSValue::cssText):
+        (WebCore::CSSValue::destroy):
+        * css/CSSValue.h:
+        (WebCore::CSSValue::isAnimationTriggerScrollValue):
+
+        * platform/animation/Animation.cpp: Make sure to initialise m_trigger and m_triggerSet,
+        and use them in the operator==.
+        * platform/animation/Animation.h: Add AnimationTrigger as a new field.
+        (WebCore::Animation::isTriggerSet):
+        (WebCore::Animation::isEmpty):
+
+        * platform/animation/AnimationTrigger.h: Added. New base class and subclasses for
+        "auto" and the scrolling trigger.
+        (WebCore::AnimationTrigger::~AnimationTrigger):
+        (WebCore::AnimationTrigger::type):
+        (WebCore::AnimationTrigger::isAutoAnimationTrigger):
+        (WebCore::AnimationTrigger::isScrollAnimationTrigger):
+        (WebCore::AnimationTrigger::AnimationTrigger):
+        (WebCore::AutoAnimationTrigger::create):
+        (WebCore::AutoAnimationTrigger::~AutoAnimationTrigger):
+        (WebCore::AutoAnimationTrigger::AutoAnimationTrigger):
+        (WebCore::ScrollAnimationTrigger::create):
+        (WebCore::ScrollAnimationTrigger::~ScrollAnimationTrigger):
+        (WebCore::ScrollAnimationTrigger::startValue):
+        (WebCore::ScrollAnimationTrigger::setStartValue):
+        (WebCore::ScrollAnimationTrigger::endValue):
+        (WebCore::ScrollAnimationTrigger::setEndValue):
+        (WebCore::ScrollAnimationTrigger::hasEndValue):
+        (WebCore::ScrollAnimationTrigger::setHasEndValue):
+        (WebCore::ScrollAnimationTrigger::ScrollAnimationTrigger):
+
 2015-03-16  Alex Christensen  <achristensen@webkit.org>
 
         Progress towards CMake on Mac
index 8625316..5ec7596 100644 (file)
                31A795C71888BCB200382F90 /* ANGLEInstancedArrays.h in Headers */ = {isa = PBXBuildFile; fileRef = 31A795C21888B72400382F90 /* ANGLEInstancedArrays.h */; };
                31A795C81888BCB500382F90 /* ANGLEInstancedArrays.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31A795C11888B72400382F90 /* ANGLEInstancedArrays.cpp */; };
                31AB5000122878A2001A7DB0 /* GraphicsContext3DIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 31AB4FFF122878A2001A7DB0 /* GraphicsContext3DIOS.h */; };
+               31BC742D1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31BC742B1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.cpp */; };
+               31BC742E1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 31BC742C1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.h */; };
                31C0FF210E4CEB6E007D6FE5 /* WebKitAnimationEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31C0FF1B0E4CEB6E007D6FE5 /* WebKitAnimationEvent.cpp */; };
                31C0FF220E4CEB6E007D6FE5 /* WebKitAnimationEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 31C0FF1C0E4CEB6E007D6FE5 /* WebKitAnimationEvent.h */; };
                31C0FF240E4CEB6E007D6FE5 /* WebKitTransitionEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31C0FF1E0E4CEB6E007D6FE5 /* WebKitTransitionEvent.cpp */; };
                31C0FF4D0E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = 31C0FF470E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.mm */; };
                31C0FF4E0E4CEFDD007D6FE5 /* DOMWebKitTransitionEventInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 31C0FF480E4CEFDD007D6FE5 /* DOMWebKitTransitionEventInternal.h */; };
                31D591B316697A6C00E6BF02 /* PlugInClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 31D591B116697A6C00E6BF02 /* PlugInClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               31DCD29D1AB4FBDE0072E817 /* AnimationTrigger.h in Headers */ = {isa = PBXBuildFile; fileRef = 31DCD29C1AB4FBDE0072E817 /* AnimationTrigger.h */; settings = {ATTRIBUTES = (Private, ); }; };
                31EAF97E121435A400E7C1BF /* DeviceMotionClientIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 31EAF97C121435A400E7C1BF /* DeviceMotionClientIOS.h */; };
                31EAF97F121435A400E7C1BF /* DeviceMotionClientIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 31EAF97D121435A400E7C1BF /* DeviceMotionClientIOS.mm */; };
                31EC1E2814FF60EE00C94662 /* JSNotificationPermissionCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31EC1E2614FF60EE00C94662 /* JSNotificationPermissionCallback.cpp */; };
                31A795C41888BAD100382F90 /* JSANGLEInstancedArrays.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSANGLEInstancedArrays.cpp; sourceTree = "<group>"; };
                31A795C51888BAD100382F90 /* JSANGLEInstancedArrays.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSANGLEInstancedArrays.h; sourceTree = "<group>"; };
                31AB4FFF122878A2001A7DB0 /* GraphicsContext3DIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphicsContext3DIOS.h; sourceTree = "<group>"; };
+               31BC742B1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSAnimationTriggerScrollValue.cpp; sourceTree = "<group>"; };
+               31BC742C1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSAnimationTriggerScrollValue.h; sourceTree = "<group>"; };
                31C0FF1B0E4CEB6E007D6FE5 /* WebKitAnimationEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitAnimationEvent.cpp; sourceTree = "<group>"; };
                31C0FF1C0E4CEB6E007D6FE5 /* WebKitAnimationEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitAnimationEvent.h; sourceTree = "<group>"; };
                31C0FF1D0E4CEB6E007D6FE5 /* WebKitAnimationEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebKitAnimationEvent.idl; sourceTree = "<group>"; };
                31C0FF470E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMWebKitTransitionEvent.mm; sourceTree = "<group>"; };
                31C0FF480E4CEFDD007D6FE5 /* DOMWebKitTransitionEventInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWebKitTransitionEventInternal.h; sourceTree = "<group>"; };
                31D591B116697A6C00E6BF02 /* PlugInClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlugInClient.h; sourceTree = "<group>"; };
+               31DCD29C1AB4FBDE0072E817 /* AnimationTrigger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnimationTrigger.h; path = animation/AnimationTrigger.h; sourceTree = "<group>"; };
                31E8D8BA160BC94B004CE8F5 /* RenderSnapshottedPlugIn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSnapshottedPlugIn.cpp; sourceTree = "<group>"; };
                31E8D8BB160BC94C004CE8F5 /* RenderSnapshottedPlugIn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSnapshottedPlugIn.h; sourceTree = "<group>"; };
                31EAF97C121435A400E7C1BF /* DeviceMotionClientIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeviceMotionClientIOS.h; path = ios/DeviceMotionClientIOS.h; sourceTree = "<group>"; };
                498770C11242C50D002226BA /* gpu */ = {
                        isa = PBXGroup;
                        children = (
-                               498771161242CD7F002226BA /* mac */,
                                498770D71242C535002226BA /* Texture.cpp */,
                                498770D81242C535002226BA /* Texture.h */,
                                498770D91242C535002226BA /* TilingData.cpp */,
                                49E912A60EFAC906009D0CAF /* Animation.h */,
                                49E912A70EFAC906009D0CAF /* AnimationList.cpp */,
                                49E912A80EFAC906009D0CAF /* AnimationList.h */,
+                               31DCD29C1AB4FBDE0072E817 /* AnimationTrigger.h */,
                                0F580FAE149800D400FB5BD8 /* AnimationUtilities.h */,
                                49E912A90EFAC906009D0CAF /* TimingFunction.h */,
                        );
                F523D18402DE42E8018635CA /* css */ = {
                        isa = PBXGroup;
                        children = (
+                               31BC742B1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.cpp */,
+                               31BC742C1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.h */,
                                83520C7D1A71BFCC006BD2AA /* CSSFontFamily.h */,
                                FBD6AF8415EF21D4008B7110 /* BasicShapeFunctions.cpp */,
                                FBD6AF8515EF21D4008B7110 /* BasicShapeFunctions.h */,
                                85BA4CDD0AA6861B0088052D /* DOMHTMLButtonElement.h in Headers */,
                                85E711A10AC5D5350053270F /* DOMHTMLButtonElementInternal.h in Headers */,
                                93D3C1590F97A9D70053C013 /* DOMHTMLCanvasElement.h in Headers */,
+                               31DCD29D1AB4FBDE0072E817 /* AnimationTrigger.h in Headers */,
                                93F9B6580BA0F35E00854064 /* DOMHTMLCanvasElementInternal.h in Headers */,
                                85DF2F8E0AA3C88100AD64C5 /* DOMHTMLCollection.h in Headers */,
                                85E711A20AC5D5350053270F /* DOMHTMLCollectionInternal.h in Headers */,
                                8518DD780A9CF31B0091B7A6 /* DOMNamedNodeMap.h in Headers */,
                                85E711D20AC5D5350053270F /* DOMNamedNodeMapInternal.h in Headers */,
                                853BF4DB0ABB6B55008647BB /* DOMNode.h in Headers */,
+                               31BC742E1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.h in Headers */,
                                854075260AD6C66700620C57 /* DOMNodeFilter.h in Headers */,
                                85B498FB0ADB340200925CBB /* DOMNodeInternal.h in Headers */,
                                85526C370AB0A17E000302EA /* DOMNodeIterator.h in Headers */,
                                B28C6A290D00C44800334AA4 /* SVGImageLoader.cpp in Sources */,
                                B2227A2F0D00BF220071B782 /* SVGLangSpace.cpp in Sources */,
                                B2227A320D00BF220071B782 /* SVGLength.cpp in Sources */,
+                               31BC742D1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.cpp in Sources */,
                                7134496D146941B300720312 /* SVGLengthContext.cpp in Sources */,
                                B2227A350D00BF220071B782 /* SVGLengthList.cpp in Sources */,
                                B2227A380D00BF220071B782 /* SVGLinearGradientElement.cpp in Sources */,
diff --git a/Source/WebCore/css/CSSAnimationTriggerScrollValue.cpp b/Source/WebCore/css/CSSAnimationTriggerScrollValue.cpp
new file mode 100644 (file)
index 0000000..7addf8a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CSSAnimationTriggerScrollValue.h"
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+String CSSAnimationTriggerScrollValue::customCSSText() const
+{
+    StringBuilder result;
+    result.append("container-scroll(");
+    result.append(m_startValue->cssText());
+    if (m_endValue) {
+        result.append(", ");
+        result.append(m_endValue->cssText());
+    }
+    result.append(')');
+    return result.toString();
+}
+
+bool CSSAnimationTriggerScrollValue::equals(const CSSAnimationTriggerScrollValue& other) const
+{
+    return m_startValue->equals(*other.m_startValue.get()) && m_endValue->equals(*other.m_endValue.get());
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/css/CSSAnimationTriggerScrollValue.h b/Source/WebCore/css/CSSAnimationTriggerScrollValue.h
new file mode 100644 (file)
index 0000000..86cc2ff
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CSSAnimationTriggerScrollValue_h
+#define CSSAnimationTriggerScrollValue_h
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class CSSAnimationTriggerScrollValue : public CSSValue {
+public:
+    static Ref<CSSAnimationTriggerScrollValue> create(PassRefPtr<CSSValue> startValue, PassRefPtr<CSSValue> endValue = nullptr)
+    {
+        return adoptRef(*new CSSAnimationTriggerScrollValue(startValue, endValue));
+    }
+
+    const CSSValue* startValue() const { return m_startValue.get(); }
+    const CSSValue* endValue() const { return m_endValue.get(); }
+    bool hasEndValue() const { return m_endValue; }
+
+    String customCSSText() const;
+
+    bool equals(const CSSAnimationTriggerScrollValue&) const;
+
+private:
+    CSSAnimationTriggerScrollValue(PassRefPtr<CSSValue> startValue, PassRefPtr<CSSValue> endValue)
+        : CSSValue(AnimationTriggerScrollClass)
+        , m_startValue(startValue)
+        , m_endValue(endValue)
+    {
+    }
+
+    RefPtr<CSSValue> m_startValue;
+    RefPtr<CSSValue> m_endValue;
+};
+
+}
+
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSAnimationTriggerScrollValue, isAnimationTriggerScrollValue())
+
+#endif
+
+#endif
index bc8f598..f867157 100644 (file)
@@ -28,6 +28,7 @@
 #include "AnimationController.h"
 #include "BasicShapeFunctions.h"
 #include "BasicShapes.h"
+#include "CSSAnimationTriggerScrollValue.h"
 #include "CSSAspectRatioValue.h"
 #include "CSSBasicShapes.h"
 #include "CSSBorderImage.h"
 #include "StyleScrollSnapPoints.h"
 #endif
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+#include "AnimationTrigger.h"
+#endif
+
 namespace WebCore {
 
 // List of all properties we know how to compute, omitting shorthands.
@@ -1221,6 +1226,37 @@ static Ref<CSSValueList> getTimingFunctionValue(const AnimationList* animList)
     return list;
 }
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+static Ref<CSSValue> createAnimationTriggerValue(const AnimationTrigger* trigger, const RenderStyle* style)
+{
+    switch (trigger->type()) {
+    case AnimationTrigger::AnimationTriggerType::ScrollAnimationTriggerType: {
+        const ScrollAnimationTrigger* scrollAnimationTrigger = static_cast<const ScrollAnimationTrigger*>(trigger);
+        if (scrollAnimationTrigger->endValue().isAuto())
+            return CSSAnimationTriggerScrollValue::create(zoomAdjustedPixelValueForLength(scrollAnimationTrigger->startValue(), style));
+        else
+            return CSSAnimationTriggerScrollValue::create(zoomAdjustedPixelValueForLength(scrollAnimationTrigger->startValue(), style),
+                                                          zoomAdjustedPixelValueForLength(scrollAnimationTrigger->endValue(), style));
+    }
+    default:
+        ASSERT(trigger->type() == AnimationTrigger::AnimationTriggerType::AutoAnimationTriggerType);
+        return cssValuePool().createIdentifierValue(CSSValueAuto);
+    }
+}
+
+static Ref<CSSValueList> getAnimationTriggerValue(const AnimationList* animList, const RenderStyle* style)
+{
+    auto list = CSSValueList::createCommaSeparated();
+    if (animList) {
+        for (size_t i = 0; i < animList->size(); ++i)
+            list.get().append(createAnimationTriggerValue(animList->animation(i).trigger().get(), style));
+    } else
+        list.get().append(createAnimationTriggerValue(Animation::initialTrigger().get(), style));
+
+    return list;
+}
+#endif
+
 static Ref<CSSValue> createLineBoxContainValue(unsigned lineBoxContain)
 {
     if (!lineBoxContain)
@@ -2720,6 +2756,10 @@ PassRefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propert
         case CSSPropertyAnimationTimingFunction:
         case CSSPropertyWebkitAnimationTimingFunction:
             return getTimingFunctionValue(style->animations());
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+        case CSSPropertyWebkitAnimationTrigger:
+            return getAnimationTriggerValue(style->animations(), style.get());
+#endif
         case CSSPropertyWebkitAppearance:
             return cssValuePool().createValue(style->appearance());
         case CSSPropertyWebkitAspectRatio:
index 84bc151..835405a 100644 (file)
@@ -28,6 +28,7 @@
 #include "config.h"
 #include "CSSParser.h"
 
+#include "CSSAnimationTriggerScrollValue.h"
 #include "CSSAspectRatioValue.h"
 #include "CSSBasicShapes.h"
 #include "CSSBorderImage.h"
@@ -2689,6 +2690,9 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
     case CSSPropertyWebkitAnimationPlayState:
     case CSSPropertyWebkitAnimationIterationCount:
     case CSSPropertyWebkitAnimationTimingFunction:
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    case CSSPropertyWebkitAnimationTrigger:
+#endif
     case CSSPropertyTransitionDelay:
     case CSSPropertyTransitionDuration:
     case CSSPropertyTransitionTimingFunction:
@@ -4743,6 +4747,51 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState()
     return nullptr;
 }
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+PassRefPtr<CSSValue> CSSParser::parseAnimationTrigger()
+{
+    CSSParserValue* value = m_valueList->current();
+    if (value->id == CSSValueAuto)
+        return cssValuePool().createIdentifierValue(CSSValueAuto);
+
+    if (value->unit != CSSParserValue::Function)
+        return nullptr;
+
+    CSSParserValueList* args = value->function->args.get();
+
+    if (equalIgnoringCase(value->function->name, "container-scroll(")) {
+        if (!args || (args->size() != 1 && args->size() != 3))
+            return nullptr;
+
+        CSSParserValue* argument = args->current();
+        ValueWithCalculation firstArgumentWithCalculation(*argument);
+        if (!validateUnit(firstArgumentWithCalculation, FLength))
+            return nullptr;
+
+        RefPtr<CSSValue> startValue = createPrimitiveNumericValue(firstArgumentWithCalculation);
+
+        argument = args->next();
+
+        if (!argument)
+            return CSSAnimationTriggerScrollValue::create(startValue.release());
+
+        if (!isComma(argument))
+            return nullptr;
+
+        argument = args->next();
+        ValueWithCalculation secondArgumentWithCalculation(*argument);
+        if (!validateUnit(secondArgumentWithCalculation, FLength))
+            return nullptr;
+
+        RefPtr<CSSValue> endValue = createPrimitiveNumericValue(secondArgumentWithCalculation);
+
+        return CSSAnimationTriggerScrollValue::create(startValue.release(), endValue.release());
+    }
+
+    return 0;
+}
+#endif
+
 PassRefPtr<CSSValue> CSSParser::parseAnimationProperty(AnimationParseContext& context)
 {
     CSSParserValue& value = *m_valueList->current();
@@ -4980,6 +5029,13 @@ bool CSSParser::parseAnimationProperty(CSSPropertyID propId, RefPtr<CSSValue>& r
                 if (currValue)
                     m_valueList->next();
                 break;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+            case CSSPropertyWebkitAnimationTrigger:
+                currValue = parseAnimationTrigger();
+                if (currValue)
+                    m_valueList->next();
+                break;
+#endif
             default:
                 ASSERT_NOT_REACHED();
                 return false;
index 535d222..87fbb63 100644 (file)
@@ -181,6 +181,9 @@ public:
     PassRefPtr<CSSValue> parseAnimationPlayState();
     PassRefPtr<CSSValue> parseAnimationProperty(AnimationParseContext&);
     PassRefPtr<CSSValue> parseAnimationTimingFunction();
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    PassRefPtr<CSSValue> parseAnimationTrigger();
+#endif
     static Vector<double> parseKeyframeSelector(const String&);
 
     bool parseTransformOriginShorthand(RefPtr<CSSValue>&, RefPtr<CSSValue>&, RefPtr<CSSValue>&);
index 121d637..03c8ee0 100644 (file)
@@ -367,6 +367,9 @@ alt [NameForMethods=ContentAltText, Custom=Value]
 -webkit-animation-name [AnimationProperty, NameForMethods=Name]
 -webkit-animation-play-state [AnimationProperty, NameForMethods=PlayState]
 -webkit-animation-timing-function [AnimationProperty, NameForMethods=TimingFunction]
+#if defined(ENABLE_CSS_ANIMATIONS_LEVEL_2) && ENABLE_CSS_ANIMATIONS_LEVEL_2
+-webkit-animation-trigger [AnimationProperty, NameForMethods=Trigger]
+#endif
 -webkit-appearance
 -webkit-aspect-ratio [Inherited, Custom=All]
 -webkit-backface-visibility
index dc61a5c..1c2980c 100644 (file)
@@ -29,6 +29,7 @@
 #include "CSSToStyleMap.h"
 
 #include "Animation.h"
+#include "CSSAnimationTriggerScrollValue.h"
 #include "CSSBorderImageSliceValue.h"
 #include "CSSImageGeneratorValue.h"
 #include "CSSImageSetValue.h"
@@ -513,6 +514,38 @@ void CSSToStyleMap::mapAnimationTimingFunction(Animation& animation, CSSValue& v
     }
 }
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+void CSSToStyleMap::mapAnimationTrigger(Animation& animation, CSSValue& value)
+{
+    if (value.isInitialValue()) {
+        animation.setTrigger(Animation::initialTrigger());
+        return;
+    }
+
+    if (value.isPrimitiveValue()) {
+        auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
+        if (primitiveValue.getValueID() == CSSValueAuto)
+            animation.setTrigger(AutoAnimationTrigger::create());
+        return;
+    }
+
+    if (value.isAnimationTriggerScrollValue()) {
+        auto& scrollTrigger = downcast<CSSAnimationTriggerScrollValue>(value);
+
+        const CSSPrimitiveValue* startValue = downcast<CSSPrimitiveValue>(scrollTrigger.startValue());
+        Length startLength = startValue->computeLength<Length>(m_resolver->state().cssToLengthConversionData());
+
+        Length endLength;
+        if (scrollTrigger.hasEndValue()) {
+            const CSSPrimitiveValue* endValue = downcast<CSSPrimitiveValue>(scrollTrigger.endValue());
+            endLength = endValue->computeLength<Length>(m_resolver->state().cssToLengthConversionData());
+        }
+
+        animation.setTrigger(ScrollAnimationTrigger::create(startLength, endLength));
+    }
+}
+#endif
+
 void CSSToStyleMap::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image)
 {
     // If we're not a value list, then we are "none" and don't need to alter the empty image at all.
index aa1b486..b5f3ee7 100644 (file)
@@ -67,6 +67,9 @@ public:
     void mapAnimationPlayState(Animation&, CSSValue&);
     void mapAnimationProperty(Animation&, CSSValue&);
     void mapAnimationTimingFunction(Animation&, CSSValue&);
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    void mapAnimationTrigger(Animation&, CSSValue&);
+#endif
 
     void mapNinePieceImage(CSSPropertyID, CSSValue*, NinePieceImage&);
     void mapNinePieceImageSlice(CSSValue&, NinePieceImage&);
index 2752343..377f6ed 100644 (file)
@@ -28,6 +28,7 @@
 #include "config.h"
 #include "CSSValue.h"
 
+#include "CSSAnimationTriggerScrollValue.h"
 #include "CSSAspectRatioValue.h"
 #include "CSSBorderImageSliceValue.h"
 #include "CSSCalculationValue.h"
@@ -226,6 +227,10 @@ bool CSSValue::equals(const CSSValue& other) const
             return compareCSSValues<SVGColor>(*this, other);
         case SVGPaintClass:
             return compareCSSValues<SVGPaint>(*this, other);
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+        case AnimationTriggerScrollClass:
+            return compareCSSValues<CSSAnimationTriggerScrollValue>(*this, other);
+#endif
         default:
             ASSERT_NOT_REACHED();
             return false;
@@ -312,6 +317,10 @@ String CSSValue::cssText() const
         return downcast<SVGColor>(*this).customCSSText();
     case SVGPaintClass:
         return downcast<SVGPaint>(*this).customCSSText();
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    case AnimationTriggerScrollClass:
+        return downcast<CSSAnimationTriggerScrollValue>(*this).customCSSText();
+#endif
     case WebKitCSSResourceClass:
         return downcast<WebKitCSSResourceValue>(*this).customCSSText();
     }
@@ -426,6 +435,11 @@ void CSSValue::destroy()
     case SVGPaintClass:
         delete downcast<SVGPaint>(this);
         return;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    case AnimationTriggerScrollClass:
+        delete downcast<CSSAnimationTriggerScrollValue>(this);
+        return;
+#endif
     case WebKitCSSResourceClass:
         delete downcast<WebKitCSSResourceValue>(this);
         return;
index 632ef9a..9f19af9 100644 (file)
@@ -105,6 +105,10 @@ public:
     bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; }
     bool isWebKitCSSResourceValue() const { return m_classType == WebKitCSSResourceClass; }
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    bool isAnimationTriggerScrollValue() const { return m_classType == AnimationTriggerScrollClass; }
+#endif
+
     bool isCSSOMSafe() const { return m_isCSSOMSafe; }
     bool isSubtypeExposedToCSSOM() const
     { 
@@ -165,6 +169,10 @@ protected:
         SVGPaintClass,
         WebKitCSSResourceClass,
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+        AnimationTriggerScrollClass,
+#endif
+
         // List class types must appear after ValueListClass.
         ValueListClass,
 #if ENABLE(CSS_IMAGE_SET)
index 3496c5a..ac050a1 100644 (file)
@@ -32,6 +32,9 @@ Animation::Animation()
     , m_delay(initialDelay())
     , m_duration(initialDuration())
     , m_timingFunction(initialTimingFunction())
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    , m_trigger(initialTrigger())
+#endif
     , m_direction(initialDirection())
     , m_fillMode(initialFillMode())
     , m_playState(initialPlayState())
@@ -44,6 +47,9 @@ Animation::Animation()
     , m_playStateSet(false)
     , m_propertySet(false)
     , m_timingFunctionSet(false)
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    , m_triggerSet(false)
+#endif
     , m_isNone(false)
 {
 }
@@ -57,6 +63,9 @@ Animation::Animation(const Animation& o)
     , m_delay(o.m_delay)
     , m_duration(o.m_duration)
     , m_timingFunction(o.m_timingFunction)
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    , m_trigger(o.m_trigger)
+#endif
     , m_direction(o.m_direction)
     , m_fillMode(o.m_fillMode)
     , m_playState(o.m_playState)
@@ -69,6 +78,9 @@ Animation::Animation(const Animation& o)
     , m_playStateSet(o.m_playStateSet)
     , m_propertySet(o.m_propertySet)
     , m_timingFunctionSet(o.m_timingFunctionSet)
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    , m_triggerSet(o.m_triggerSet)
+#endif
     , m_isNone(o.m_isNone)
 {
 }
@@ -85,6 +97,9 @@ Animation& Animation::operator=(const Animation& o)
     m_direction = o.m_direction;
     m_fillMode = o.m_fillMode;
     m_playState = o.m_playState;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    m_trigger = o.m_trigger;
+#endif
 
     m_delaySet = o.m_delaySet;
     m_directionSet = o.m_directionSet;
@@ -95,6 +110,9 @@ Animation& Animation::operator=(const Animation& o)
     m_playStateSet = o.m_playStateSet;
     m_propertySet = o.m_propertySet;
     m_timingFunctionSet = o.m_timingFunctionSet;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    m_triggerSet = o.m_triggerSet;
+#endif
     m_isNone = o.m_isNone;
 
     return *this;
@@ -116,6 +134,9 @@ bool Animation::animationsMatch(const Animation* o, bool matchPlayStates) const
                   && m_delay == o->m_delay
                   && m_duration == o->m_duration
                   && *(m_timingFunction.get()) == *(o->m_timingFunction.get())
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+                  && *(m_trigger.get()) == *(o->m_trigger.get())
+#endif
                   && m_direction == o->m_direction
                   && m_fillMode == o->m_fillMode
                   && m_delaySet == o->m_delaySet
@@ -126,6 +147,9 @@ bool Animation::animationsMatch(const Animation* o, bool matchPlayStates) const
                   && m_nameSet == o->m_nameSet
                   && m_propertySet == o->m_propertySet
                   && m_timingFunctionSet == o->m_timingFunctionSet
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+                  && m_triggerSet == o->m_triggerSet
+#endif
                   && m_isNone == o->m_isNone;
 
     if (!result)
index e16384f..c6958f4 100644 (file)
@@ -25,6 +25,9 @@
 #ifndef Animation_h
 #define Animation_h
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+#include "AnimationTrigger.h"
+#endif
 #include "CSSPropertyNames.h"
 #include "RenderStyleConstants.h"
 #include "TimingFunction.h"
@@ -50,6 +53,9 @@ public:
     bool isPlayStateSet() const { return m_playStateSet; }
     bool isPropertySet() const { return m_propertySet; }
     bool isTimingFunctionSet() const { return m_timingFunctionSet; }
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    bool isTriggerSet() const { return m_triggerSet; }
+#endif
 
     // Flags this to be the special "none" animation (animation-name: none)
     bool isNoneAnimation() const { return m_isNone; }
@@ -61,7 +67,12 @@ public:
     {
         return (!m_directionSet && !m_durationSet && !m_fillModeSet
                 && !m_nameSet && !m_playStateSet && !m_iterationCountSet
-                && !m_delaySet && !m_timingFunctionSet && !m_propertySet);
+                && !m_delaySet && !m_timingFunctionSet && !m_propertySet
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+                && !m_triggerSet);
+#else
+                );
+#endif
     }
 
     bool isEmptyOrZeroDuration() const
@@ -78,6 +89,9 @@ public:
     void clearPlayState() { m_playStateSet = AnimPlayStatePlaying; }
     void clearProperty() { m_propertySet = false; }
     void clearTimingFunction() { m_timingFunctionSet = false; }
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    void clearTrigger() { m_triggerSet = false; }
+#endif
 
     void clearAll()
     {
@@ -90,6 +104,9 @@ public:
         clearPlayState();
         clearProperty();
         clearTimingFunction();
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+        clearTrigger();
+#endif
     }
 
     double delay() const { return m_delay; }
@@ -118,8 +135,11 @@ public:
     const String& name() const { return m_name; }
     EAnimPlayState playState() const { return static_cast<EAnimPlayState>(m_playState); }
     CSSPropertyID property() const { return m_property; }
-    const PassRefPtr<TimingFunction> timingFunction() const { return m_timingFunction; }
+    PassRefPtr<TimingFunction> timingFunction() const { return m_timingFunction; }
     AnimationMode animationMode() const { return m_mode; }
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    PassRefPtr<AnimationTrigger> trigger() const { return m_trigger; }
+#endif
 
     void setDelay(double c) { m_delay = c; m_delaySet = true; }
     void setDirection(AnimationDirection d) { m_direction = d; m_directionSet = true; }
@@ -131,6 +151,9 @@ public:
     void setProperty(CSSPropertyID t) { m_property = t; m_propertySet = true; }
     void setTimingFunction(PassRefPtr<TimingFunction> f) { m_timingFunction = f; m_timingFunctionSet = true; }
     void setAnimationMode(AnimationMode mode) { m_mode = mode; }
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    void setTrigger(PassRefPtr<AnimationTrigger> t) { m_trigger = t; m_triggerSet = true; }
+#endif
 
     void setIsNoneAnimation(bool n) { m_isNone = n; }
 
@@ -157,9 +180,13 @@ private:
     double m_delay;
     double m_duration;
     RefPtr<TimingFunction> m_timingFunction;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    RefPtr<AnimationTrigger> m_trigger;
+#endif
     unsigned m_direction : 2; // AnimationDirection
     unsigned m_fillMode : 2;
 
+
     unsigned m_playState     : 2;
 
     bool m_delaySet          : 1;
@@ -171,7 +198,10 @@ private:
     bool m_playStateSet      : 1;
     bool m_propertySet       : 1;
     bool m_timingFunctionSet : 1;
-    
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    bool m_triggerSet        : 1;
+#endif
+
     bool m_isNone            : 1;
 
 public:
@@ -184,6 +214,9 @@ public:
     static EAnimPlayState initialPlayState() { return AnimPlayStatePlaying; }
     static CSSPropertyID initialProperty() { return CSSPropertyInvalid; }
     static const PassRefPtr<TimingFunction> initialTimingFunction() { return CubicBezierTimingFunction::create(); }
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    static const PassRefPtr<AnimationTrigger> initialTrigger() { return AutoAnimationTrigger::create(); }
+#endif
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/animation/AnimationTrigger.h b/Source/WebCore/platform/animation/AnimationTrigger.h
new file mode 100644 (file)
index 0000000..1e131a2
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AnimationTrigger_h
+#define AnimationTrigger_h
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+
+#include "Length.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class AnimationTrigger : public RefCounted<AnimationTrigger> {
+public:
+
+    virtual PassRefPtr<AnimationTrigger> clone() const = 0;
+
+    enum class AnimationTriggerType {
+        AutoAnimationTriggerType, ScrollAnimationTriggerType
+    };
+
+    virtual ~AnimationTrigger() { }
+
+    AnimationTriggerType type() const { return m_type; }
+
+    bool isAutoAnimationTrigger() const { return m_type == AnimationTriggerType::AutoAnimationTriggerType; }
+    bool isScrollAnimationTrigger() const { return m_type == AnimationTriggerType::ScrollAnimationTriggerType; }
+
+    virtual bool operator==(const AnimationTrigger& other) = 0;
+
+protected:
+    AnimationTrigger(AnimationTriggerType type)
+        : m_type(type)
+    {
+    }
+
+    AnimationTriggerType m_type;
+};
+
+class AutoAnimationTrigger : public AnimationTrigger {
+public:
+    static PassRefPtr<AutoAnimationTrigger> create()
+    {
+        return adoptRef(new AutoAnimationTrigger);
+    }
+
+    virtual ~AutoAnimationTrigger() { }
+
+    virtual bool operator==(const AnimationTrigger& other) override
+    {
+        return other.isAutoAnimationTrigger();
+    }
+
+private:
+    AutoAnimationTrigger()
+        : AnimationTrigger(AnimationTriggerType::AutoAnimationTriggerType)
+    {
+    }
+
+    virtual PassRefPtr<AnimationTrigger> clone() const override
+    {
+        return adoptRef(new AutoAnimationTrigger);
+    }
+};
+
+class ScrollAnimationTrigger : public AnimationTrigger {
+public:
+    static PassRefPtr<ScrollAnimationTrigger> create(Length startValue, Length endValue , bool hasEndValue = false)
+    {
+        return adoptRef(new ScrollAnimationTrigger(startValue, endValue, hasEndValue));
+    }
+
+    virtual ~ScrollAnimationTrigger() { }
+
+    virtual bool operator==(const AnimationTrigger& other) override
+    {
+        if (!other.isScrollAnimationTrigger())
+            return false;
+
+        const ScrollAnimationTrigger* otherTrigger = static_cast<const ScrollAnimationTrigger*>(&other);
+        return m_startValue == otherTrigger->m_startValue
+            && m_endValue == otherTrigger->m_endValue
+            && m_hasEndValue == otherTrigger->m_hasEndValue;
+    }
+
+    Length startValue() const { return m_startValue; }
+
+    void setStartValue(Length value)
+    {
+        m_startValue = value;
+    }
+
+    Length endValue() const { return m_endValue; }
+
+    void setEndValue(Length value)
+    {
+        m_endValue = value;
+    }
+
+    bool hasEndValue() const { return m_hasEndValue; }
+
+    void setHasEndValue(bool value)
+    {
+        m_hasEndValue = value;
+    }
+
+private:
+    explicit ScrollAnimationTrigger(Length startValue, Length endValue, bool hasEndValue)
+        : AnimationTrigger(AnimationTriggerType::ScrollAnimationTriggerType)
+        , m_startValue(startValue)
+        , m_endValue(endValue)
+        , m_hasEndValue(hasEndValue)
+    {
+    }
+
+    virtual PassRefPtr<AnimationTrigger> clone() const override
+    {
+        return adoptRef(new ScrollAnimationTrigger(m_startValue, m_endValue, m_hasEndValue));
+    }
+
+    Length m_startValue;
+    Length m_endValue;
+    bool m_hasEndValue;
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // AnimationTrigger_h