diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/animation')
47 files changed, 698 insertions, 200 deletions
diff --git a/chromium/third_party/blink/renderer/core/animation/BUILD.gn b/chromium/third_party/blink/renderer/core/animation/BUILD.gn index b96fc0b8da2..8dcf27c7d56 100644 --- a/chromium/third_party/blink/renderer/core/animation/BUILD.gn +++ b/chromium/third_party/blink/renderer/core/animation/BUILD.gn @@ -182,6 +182,8 @@ blink_core_sources("animation") { "sampled_effect.h", "scroll_timeline.cc", "scroll_timeline.h", + "scroll_timeline_util.cc", + "scroll_timeline_util.h", "shadow_interpolation_functions.cc", "shadow_interpolation_functions.h", "side_index.h", diff --git a/chromium/third_party/blink/renderer/core/animation/README.md b/chromium/third_party/blink/renderer/core/animation/README.md index e6ffefb1335..9481e72d44f 100644 --- a/chromium/third_party/blink/renderer/core/animation/README.md +++ b/chromium/third_party/blink/renderer/core/animation/README.md @@ -61,8 +61,8 @@ The Blink animation engine interacts with Blink/Chrome in the following ways: A subset of style properties (currently transform, opacity, filter, and backdrop-filter) can be mutated on the compositor thread. Animations that - mutates only these properties are a candidate for being accelerated and run - on compositor thread which ensures they are isolated from Blink's main + mutate only these properties are candidates for being accelerated and run + on the compositor thread which ensures they are isolated from Blink's main thread work. Whether or not an animation can be accelerated is determined by @@ -74,7 +74,7 @@ The Blink animation engine interacts with Blink/Chrome in the following ways: #### Lifetime of a compositor animation Animations that can be accelerated get added to the [PendingAnimations][] - list. The pending list is updates as part of document lifecycle and ensures + list. The pending list is updated as part of document lifecycle and ensures each pending animation gets a corresponding [cc::AnimationPlayer][] representing the animation on the compositor. The player is initialized with appropriate timing values and corresponding effects. @@ -91,20 +91,20 @@ The Blink animation engine interacts with Blink/Chrome in the following ways: animations do not cause spurious commits from main to compositor (See [CompositedLayerMapping::UpdateGraphicsLayerGeometry()][]) - A compositor animation provide updates on its playback state changes (e.g., + A compositor animation provides updates on its playback state changes (e.g., on start, finish, abort) to its blink counterpart via [CompositorAnimationDelegate][] interface. Blink animation uses the start event callback to obtain an accurate start time for the animation which is important to ensure its output accurately reflects the compositor animation output. -[CheckCanStartAnimationOnCompositor()]: https://cs.chromium.org/search/?q=file:Animation.h+function:CheckCanStartAnimationOnCompositor +[CheckCanStartAnimationOnCompositor()]: https://cs.chromium.org/search/?q=file:animation.h+function:CheckCanStartAnimationOnCompositor [FailureCodes]: https://cs.chromium.org/search/?q=return%5Cs%2B(CompositorAnimations::)?FailureCode [cc::AnimationPlayer]: https://cs.chromium.org/search/?q=file:src/cc/animation/animation_player.h+class:AnimationPlayer -[PendingAnimations]: https://cs.chromium.org/search/?q=file:PendingAnimations.h+class:PendingAnimations -[Animation::PreCommit()]: https://cs.chromium.org/search/?q=file:Animation.h+function:PreCommit -[CompositorAnimationDelegate]: https://cs.chromium.org/search/?q=file:CompositorAnimationDelegate.h -[CompositedLayerMapping::UpdateGraphicsLayerGeometry()]: https://cs.chromium.org/search/?q=file:CompositedLayerMapping.h+function:UpdateGraphicsLayerGeometry +[PendingAnimations]: https://cs.chromium.org/search/?q=file:pending_animations.h+class:PendingAnimations +[Animation::PreCommit()]: https://cs.chromium.org/search/?q=file:animation.h+function:PreCommit +[CompositorAnimationDelegate]: https://cs.chromium.org/search/?q=file:compositor_animation_delegate.h +[CompositedLayerMapping::UpdateGraphicsLayerGeometry()]: https://cs.chromium.org/search/?q=file:composited_layer_mapping.h+function:UpdateGraphicsLayerGeometry * ### Javascript @@ -358,9 +358,9 @@ manually construct an instance of your object to [extending RenderingTest][] where you can load HTML, [enable compositing][] if necessary, and run assertions about the state. -[extending Test]: https://cs.chromium.org/search/?q=public%5C+testing::Test+file:core%5C/Animation&sq=package:chromium&type=cs +[extending Test]: https://cs.chromium.org/search/?q=public%5C+testing::Test+file:core%5C/animation&sq=package:chromium&type=cs [extending RenderingTest]: https://cs.chromium.org/search/?q=public%5C+RenderingTest+file:core%5C/animation&type=cs -[enable compositing]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/animation/compositor_animations_test.cc?type=cs&sq=package:chromium&q=file:core%5C/animation%5C/.*Test%5C.cpp+EnableCompositing +[enable compositing]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/animation/compositor_animations_test.cc?type=cs&sq=package:chromium&q=file:core%5C/animation%5C/.*test%5C.cpp+EnableCompositing ## Ongoing work @@ -384,4 +384,4 @@ web animation but it allows the animation itself to be highly customized in Javascript by providing an `animate` callback. These animations run inside an isolated worklet global scope. -[WorkletAnimation]: https://cs.chromium.org/search/?q=file:animationworklet/WorkletAnimation.h+class:WorkletAnimation +[WorkletAnimation]: https://cs.chromium.org/search/?q=file:animationworklet/worklet_animation.h+class:WorkletAnimation diff --git a/chromium/third_party/blink/renderer/core/animation/animatable/animatable_double.h b/chromium/third_party/blink/renderer/core/animation/animatable/animatable_double.h index aba5ff02ad4..d9c379963d6 100644 --- a/chromium/third_party/blink/renderer/core/animation/animatable/animatable_double.h +++ b/chromium/third_party/blink/renderer/core/animation/animatable/animatable_double.h @@ -38,10 +38,11 @@ namespace blink { class CORE_EXPORT AnimatableDouble final : public AnimatableValue { public: + AnimatableDouble(double number) : number_(number) {} ~AnimatableDouble() override = default; static AnimatableDouble* Create(double number) { - return new AnimatableDouble(number); + return MakeGarbageCollected<AnimatableDouble>(number); } double ToDouble() const { return number_; } @@ -51,7 +52,6 @@ class CORE_EXPORT AnimatableDouble final : public AnimatableValue { double fraction) const override; private: - AnimatableDouble(double number) : number_(number) {} AnimatableType GetType() const override { return kTypeDouble; } double number_; diff --git a/chromium/third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h b/chromium/third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h index 10814622a15..cdb0ab7378f 100644 --- a/chromium/third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h +++ b/chromium/third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h @@ -41,9 +41,11 @@ class AnimatableFilterOperations final : public AnimatableValue { public: static AnimatableFilterOperations* Create( const FilterOperations& operations) { - return new AnimatableFilterOperations(operations); + return MakeGarbageCollected<AnimatableFilterOperations>(operations); } + AnimatableFilterOperations(const FilterOperations& operations) + : operation_wrapper_(FilterOperationsWrapper::Create(operations)) {} ~AnimatableFilterOperations() override = default; const FilterOperations& Operations() const { @@ -57,9 +59,6 @@ class AnimatableFilterOperations final : public AnimatableValue { double fraction) const override; private: - AnimatableFilterOperations(const FilterOperations& operations) - : operation_wrapper_(FilterOperationsWrapper::Create(operations)) {} - AnimatableType GetType() const override { return kTypeFilterOperations; } Member<FilterOperationsWrapper> operation_wrapper_; diff --git a/chromium/third_party/blink/renderer/core/animation/animatable/animatable_transform.h b/chromium/third_party/blink/renderer/core/animation/animatable/animatable_transform.h index 10842bf4e4c..817c57a7a71 100644 --- a/chromium/third_party/blink/renderer/core/animation/animatable/animatable_transform.h +++ b/chromium/third_party/blink/renderer/core/animation/animatable/animatable_transform.h @@ -39,10 +39,14 @@ namespace blink { class CORE_EXPORT AnimatableTransform final : public AnimatableValue { public: + explicit AnimatableTransform(const TransformOperations& transform, + double zoom) + : transform_(transform), zoom_(zoom) {} ~AnimatableTransform() override = default; + static AnimatableTransform* Create(const TransformOperations& transform, double zoom) { - return new AnimatableTransform(transform, zoom); + return MakeGarbageCollected<AnimatableTransform>(transform, zoom); } const TransformOperations& GetTransformOperations() const { return transform_; @@ -54,9 +58,6 @@ class CORE_EXPORT AnimatableTransform final : public AnimatableValue { double fraction) const override; private: - explicit AnimatableTransform(const TransformOperations& transform, - double zoom) - : transform_(transform), zoom_(zoom) {} AnimatableType GetType() const override { return kTypeTransform; } const TransformOperations transform_; diff --git a/chromium/third_party/blink/renderer/core/animation/animation.cc b/chromium/third_party/blink/renderer/core/animation/animation.cc index bab13cab062..7dad569a20d 100644 --- a/chromium/third_party/blink/renderer/core/animation/animation.cc +++ b/chromium/third_party/blink/renderer/core/animation/animation.cc @@ -80,7 +80,7 @@ Animation* Animation::Create(AnimationEffect* effect, DocumentTimeline* subtimeline = ToDocumentTimeline(timeline); - Animation* animation = new Animation( + Animation* animation = MakeGarbageCollected<Animation>( subtimeline->GetDocument()->ContextDocument(), *subtimeline, effect); if (subtimeline) { @@ -685,9 +685,9 @@ void Animation::finish(ExceptionState& exception_state) { ScriptPromise Animation::finished(ScriptState* script_state) { if (!finished_promise_) { - finished_promise_ = - new AnimationPromise(ExecutionContext::From(script_state), this, - AnimationPromise::kFinished); + finished_promise_ = MakeGarbageCollected<AnimationPromise>( + ExecutionContext::From(script_state), this, + AnimationPromise::kFinished); if (PlayStateInternal() == kFinished) finished_promise_->Resolve(this); } @@ -696,8 +696,8 @@ ScriptPromise Animation::finished(ScriptState* script_state) { ScriptPromise Animation::ready(ScriptState* script_state) { if (!ready_promise_) { - ready_promise_ = new AnimationPromise(ExecutionContext::From(script_state), - this, AnimationPromise::kReady); + ready_promise_ = MakeGarbageCollected<AnimationPromise>( + ExecutionContext::From(script_state), this, AnimationPromise::kReady); if (PlayStateInternal() != kPending) ready_promise_->Resolve(this); } @@ -1318,7 +1318,7 @@ void Animation::Trace(blink::Visitor* visitor) { Animation::CompositorAnimationHolder* Animation::CompositorAnimationHolder::Create(Animation* animation) { - return new CompositorAnimationHolder(animation); + return MakeGarbageCollected<CompositorAnimationHolder>(animation); } Animation::CompositorAnimationHolder::CompositorAnimationHolder( diff --git a/chromium/third_party/blink/renderer/core/animation/animation.h b/chromium/third_party/blink/renderer/core/animation/animation.h index de4b82499fc..c4a6db7c401 100644 --- a/chromium/third_party/blink/renderer/core/animation/animation.h +++ b/chromium/third_party/blink/renderer/core/animation/animation.h @@ -93,6 +93,7 @@ class CORE_EXPORT Animation final : public EventTargetWithInlineData, AnimationTimeline*, ExceptionState&); + Animation(ExecutionContext*, DocumentTimeline&, AnimationEffect*); ~Animation() override; void Dispose(); @@ -233,8 +234,6 @@ class CORE_EXPORT Animation final : public EventTargetWithInlineData, RegisteredEventListener&) override; private: - Animation(ExecutionContext*, DocumentTimeline&, AnimationEffect*); - void ClearOutdated(); void ForceServiceOnNextFrame(); @@ -356,6 +355,8 @@ class CORE_EXPORT Animation final : public EventTargetWithInlineData, public: static CompositorAnimationHolder* Create(Animation*); + explicit CompositorAnimationHolder(Animation*); + void Detach(); void Trace(blink::Visitor* visitor) { visitor->Trace(animation_); } @@ -365,8 +366,6 @@ class CORE_EXPORT Animation final : public EventTargetWithInlineData, } private: - explicit CompositorAnimationHolder(Animation*); - void Dispose(); std::unique_ptr<CompositorAnimation> compositor_animation_; diff --git a/chromium/third_party/blink/renderer/core/animation/animation_effect.cc b/chromium/third_party/blink/renderer/core/animation/animation_effect.cc index 5adbdf56aa9..ffd0a17316a 100644 --- a/chromium/third_party/blink/renderer/core/animation/animation_effect.cc +++ b/chromium/third_party/blink/renderer/core/animation/animation_effect.cc @@ -180,9 +180,15 @@ void AnimationEffect::UpdateInheritedTime(double inherited_time, double time_to_next_iteration = std::numeric_limits<double>::infinity(); if (needs_update) { const double active_duration = RepeatedDuration(); + // TODO(yigu): Direction of WorkletAnimation is always forwards based on + // the calculation. Need to unify the logic to handle it correctly. + // https://crbug.com/896249. + const AnimationDirection direction = + (GetAnimation() && GetAnimation()->playbackRate() < 0) ? kBackwards + : kForwards; const Phase current_phase = - CalculatePhase(active_duration, local_time, timing_); + CalculatePhase(active_duration, local_time, direction, timing_); // FIXME: parentPhase depends on groups being implemented. const AnimationEffect::Phase kParentPhase = AnimationEffect::kPhaseActive; const double active_time = CalculateActiveTime( @@ -227,12 +233,21 @@ void AnimationEffect::UpdateInheritedTime(double inherited_time, const double local_active_duration = kLocalIterationDuration * timing_.iteration_count; DCHECK_GE(local_active_duration, 0); + const double end_time = std::max( + timing_.start_delay + active_duration + timing_.end_delay, 0.0); + const double before_active_boundary_time = + std::max(std::min(timing_.start_delay, end_time), 0.0); + // local_local_time should be greater than or equal to the + // before_active_boundary_time once the local_time goes past the start + // delay. const double local_local_time = local_time < timing_.start_delay ? local_time - : local_active_duration + timing_.start_delay; - const AnimationEffect::Phase local_current_phase = - CalculatePhase(local_active_duration, local_local_time, timing_); + : std::max(local_active_duration + timing_.start_delay, + before_active_boundary_time); + + const AnimationEffect::Phase local_current_phase = CalculatePhase( + local_active_duration, local_local_time, direction, timing_); const double local_active_time = CalculateActiveTime( local_active_duration, ResolvedFillMode(timing_.fill_mode, IsKeyframeEffect()), diff --git a/chromium/third_party/blink/renderer/core/animation/animation_effect.h b/chromium/third_party/blink/renderer/core/animation/animation_effect.h index 502a8d4f7a3..feb3b477363 100644 --- a/chromium/third_party/blink/renderer/core/animation/animation_effect.h +++ b/chromium/third_party/blink/renderer/core/animation/animation_effect.h @@ -82,6 +82,12 @@ class CORE_EXPORT AnimationEffect : public ScriptWrappable { kPhaseAfter, kPhaseNone, }; + // Represents the animation direction from the Web Animations spec, see + // https://drafts.csswg.org/web-animations-1/#animation-direction. + enum AnimationDirection { + kForwards, + kBackwards, + }; class EventDelegate : public GarbageCollectedFinalized<EventDelegate> { public: diff --git a/chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc b/chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc index 3e215ff26c2..557ed22d95e 100644 --- a/chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc +++ b/chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc @@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/animation/animation_input_helpers.h" +#include "base/stl_util.h" #include "third_party/blink/renderer/core/animation/property_handle.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" @@ -200,7 +201,7 @@ const AttributeNameMap& GetSupportedAttributes() { &svg_names::kYChannelSelectorAttr, &svg_names::kZAttr, }; - for (size_t i = 0; i < arraysize(attributes); i++) { + for (size_t i = 0; i < base::size(attributes); i++) { DCHECK(!SVGElement::IsAnimatableCSSProperty(*attributes[i])); supported_attributes.Set(*attributes[i], attributes[i]); } diff --git a/chromium/third_party/blink/renderer/core/animation/animation_test.cc b/chromium/third_party/blink/renderer/core/animation/animation_test.cc index ef9d2620489..c0a9e879bd5 100644 --- a/chromium/third_party/blink/renderer/core/animation/animation_test.cc +++ b/chromium/third_party/blink/renderer/core/animation/animation_test.cc @@ -869,7 +869,7 @@ TEST_F(AnimationAnimationTest, PauseAfterCancel) { } TEST_F(AnimationAnimationTest, NoCompositeWithoutCompositedElementId) { - ScopedSlimmingPaintV2ForTest enable_s_pv2(true); + ScopedCompositeAfterPaintForTest enable_cap(true); SetBodyInnerHTML( "<div id='foo' style='position: relative'></div>" diff --git a/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc b/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc index 1cc872bd6af..45d30eb9965 100644 --- a/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc +++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc @@ -146,7 +146,7 @@ bool HasIncompatibleAnimations(const Element& target_element, CompositorElementIdNamespace CompositorElementNamespaceForProperty( CSSPropertyID property) { if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() && - !RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { + !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { // Pre-BlinkGenPropertyTrees, all animations affect the primary // ElementId namespace. return CompositorElementIdNamespace::kPrimary; @@ -327,7 +327,7 @@ CompositorAnimations::CheckCanStartElementOnCompositor( return FailureCode::NonActionable("Accelerated animations are disabled"); } - if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { // We query paint property tree state below to determine whether the // animation is compositable. There is a known lifecycle violation where an // animation can be cancelled during style update. See @@ -504,8 +504,8 @@ void CompositorAnimations::AttachCompositedLayers( PaintLayer* layer = ToLayoutBoxModelObject(element.GetLayoutObject())->Layer(); - // Composited animations do not depend on a composited layer mapping for SPv2. - if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { + // Composited animations do not depend on a composited layer mapping for CAP. + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { if (!layer->IsAllowedToQueryCompositingState() || !layer->GetCompositedLayerMapping() || !layer->GetCompositedLayerMapping()->MainGraphicsLayer()) @@ -524,7 +524,7 @@ void CompositorAnimations::AttachCompositedLayers( // Currently we use the kPrimaryEffect node to know if nodes have been // created for animations. if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || - RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { + RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { element_id_namespace = CompositorElementIdNamespace::kPrimaryEffect; } compositor_animation->AttachElement(CompositorElementIdFromUniqueObjectId( diff --git a/chromium/third_party/blink/renderer/core/animation/compositor_animations.h b/chromium/third_party/blink/renderer/core/animation/compositor_animations.h index 30d53abb1b7..84413c1043a 100644 --- a/chromium/third_party/blink/renderer/core/animation/compositor_animations.h +++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations.h @@ -149,9 +149,9 @@ class CORE_EXPORT CompositorAnimations { friend class AnimationCompositorAnimationsTest; FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest, - CanStartElementOnCompositorTransformSPv2); + CanStartElementOnCompositorTransformCAP); FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest, - CanStartElementOnCompositorEffectSPv2); + CanStartElementOnCompositorEffectCAP); FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest, CanStartElementOnCompositorEffect); FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest, diff --git a/chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc index a8154a61f89..d27d062cf5f 100644 --- a/chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc @@ -287,8 +287,17 @@ class AnimationCompositorAnimationsTest : public RenderingTest { class AnimatableMockStringKeyframe : public StringKeyframe { public: static StringKeyframe* Create(double offset) { - return new AnimatableMockStringKeyframe(offset); + return MakeGarbageCollected<AnimatableMockStringKeyframe>(offset); } + + AnimatableMockStringKeyframe(double offset) + : StringKeyframe(), + property_specific_( + MakeGarbageCollected< + AnimatableMockPropertySpecificStringKeyframe>(offset)) { + SetOffset(offset); + } + Keyframe::PropertySpecificKeyframe* CreatePropertySpecificKeyframe( const PropertyHandle&, EffectModel::CompositeOperation, @@ -347,12 +356,6 @@ class AnimationCompositorAnimationsTest : public RenderingTest { }; Member<PropertySpecificKeyframe> property_specific_; - AnimatableMockStringKeyframe(double offset) - : StringKeyframe(), - property_specific_( - new AnimatableMockPropertySpecificStringKeyframe(offset)) { - SetOffset(offset); - } }; StringKeyframe* CreateAnimatableReplaceKeyframe(CSSPropertyID id, @@ -461,7 +464,8 @@ class AnimationCompositorAnimationsTest : public RenderingTest { LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); } void BeginFrame() { - helper_.GetWebView()->BeginFrame(WTF::CurrentTimeTicks()); + helper_.GetWebView()->MainFrameWidget()->BeginFrame( + WTF::CurrentTimeTicks()); } void ForceFullCompositingUpdate() { @@ -1756,13 +1760,13 @@ void UpdateDummyEffectNode(ObjectPaintProperties& properties, } // namespace TEST_F(AnimationCompositorAnimationsTest, - CanStartElementOnCompositorTransformSPv2) { + CanStartElementOnCompositorTransformCAP) { Persistent<Element> element = GetDocument().CreateElementForBinding("shared"); LayoutObjectProxy* layout_object = LayoutObjectProxy::Create(element.Get()); layout_object->EnsureIdForTestingProxy(); element->SetLayoutObject(layout_object); - ScopedSlimmingPaintV2ForTest enable_s_pv2(true); + ScopedCompositeAfterPaintForTest enable_cap(true); auto& properties = layout_object->GetMutableForPainting() .FirstFragment() .EnsurePaintProperties(); @@ -1789,13 +1793,13 @@ TEST_F(AnimationCompositorAnimationsTest, } TEST_F(AnimationCompositorAnimationsTest, - CanStartElementOnCompositorEffectSPv2) { + CanStartElementOnCompositorEffectCAP) { Persistent<Element> element = GetDocument().CreateElementForBinding("shared"); LayoutObjectProxy* layout_object = LayoutObjectProxy::Create(element.Get()); layout_object->EnsureIdForTestingProxy(); element->SetLayoutObject(layout_object); - ScopedSlimmingPaintV2ForTest enable_s_pv2(true); + ScopedCompositeAfterPaintForTest enable_cap(true); auto& properties = layout_object->GetMutableForPainting() .FirstFragment() .EnsurePaintProperties(); @@ -1891,7 +1895,7 @@ TEST_F(AnimationCompositorAnimationsTest, CanStartElementOnCompositorEffect) { Element* target = document->getElementById("target"); const ObjectPaintProperties* properties = target->GetLayoutObject()->FirstFragment().PaintProperties(); - if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) EXPECT_TRUE(properties->Transform()->HasDirectCompositingReasons()); CompositorAnimations::FailureCode code = CompositorAnimations::CheckCanStartElementOnCompositor(*target); diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc b/chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc index 529e50a61c6..9f111cf0378 100644 --- a/chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc +++ b/chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc @@ -7,7 +7,7 @@ #include "third_party/blink/renderer/core/animation/element_animations.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/layout/layout_object.h" -#include "third_party/blink/renderer/core/paint/stub_chrome_client_for_spv2.h" +#include "third_party/blink/renderer/core/paint/stub_chrome_client_for_cap.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/platform/animation/compositor_animation_delegate.h" @@ -16,7 +16,7 @@ namespace blink { class CSSAnimationsTest : public RenderingTest { public: CSSAnimationsTest() - : chrome_client_(MakeGarbageCollected<StubChromeClientForSPv2>()) { + : chrome_client_(MakeGarbageCollected<StubChromeClientForCAP>()) { EnablePlatform(); platform()->SetThreadedAnimationEnabled(true); } @@ -58,7 +58,7 @@ class CSSAnimationsTest : public RenderingTest { } private: - Persistent<StubChromeClientForSPv2> chrome_client_; + Persistent<StubChromeClientForCAP> chrome_client_; }; // Verify that a composited animation is retargeted according to its composited diff --git a/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc index 924a3ab7893..fa2106da6b8 100644 --- a/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc +++ b/chromium/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc @@ -159,10 +159,9 @@ Color CSSColorInterpolationType::ResolveInterpolableColor( if (alpha == 0) return Color::kTransparent; - return MakeRGBA(static_cast<int>(round(red / alpha)), - static_cast<int>(round(green / alpha)), - static_cast<int>(round(blue / alpha)), - static_cast<int>(round(alpha))); + return MakeRGBA( + clampTo<int>(round(red / alpha)), clampTo<int>(round(green / alpha)), + clampTo<int>(round(blue / alpha)), clampTo<int>(round(alpha))); } class InheritedColorChecker diff --git a/chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc index 34b35395972..75df242561c 100644 --- a/chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc +++ b/chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc @@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/animation/underlying_length_checker.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/css_value_list.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc index a363e1f7bbc..2eb8bc30487 100644 --- a/chromium/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc +++ b/chromium/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc @@ -11,6 +11,7 @@ #include "third_party/blink/renderer/core/css/css_font_variation_value.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/platform/wtf/math_extras.h" namespace blink { @@ -210,10 +211,11 @@ void CSSFontVariationSettingsInterpolationType::ApplyStandardPropertyValue( scoped_refptr<FontVariationSettings> settings = FontVariationSettings::Create(); wtf_size_t length = numbers.length(); + // Do clampTo here, which follows the same logic as ConsumeFontVariationTag. for (wtf_size_t i = 0; i < length; ++i) { settings->Append(FontVariationAxis( tags[i], - static_cast<float>(ToInterpolableNumber(numbers.Get(i))->Value()))); + clampTo<float>(ToInterpolableNumber(numbers.Get(i))->Value()))); } state.GetFontBuilder().SetVariationSettings(settings); } diff --git a/chromium/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc index 504e59f143d..893589c499c 100644 --- a/chromium/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc +++ b/chromium/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc @@ -14,6 +14,7 @@ #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc index 849c0e9d55e..b26f3124b8d 100644 --- a/chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc +++ b/chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc @@ -16,6 +16,7 @@ #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/animation/css_offset_rotate_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_offset_rotate_interpolation_type.cc index c127a212707..85736429f12 100644 --- a/chromium/third_party/blink/renderer/core/animation/css_offset_rotate_interpolation_type.cc +++ b/chromium/third_party/blink/renderer/core/animation/css_offset_rotate_interpolation_type.cc @@ -174,7 +174,7 @@ void CSSOffsetRotateInterpolationType::ApplyStandardPropertyValue( const NonInterpolableValue* non_interpolable_value, StyleResolverState& state) const { state.Style()->SetOffsetRotate(StyleOffsetRotation( - ToInterpolableNumber(interpolable_value).Value(), + clampTo<float>(ToInterpolableNumber(interpolable_value).Value()), ToCSSOffsetRotationNonInterpolableValue(*non_interpolable_value) .RotationType())); } diff --git a/chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc index 0071b81ef8d..e3018530ffa 100644 --- a/chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc +++ b/chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc @@ -17,6 +17,7 @@ #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/core/style/shadow_list.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc index 8fb1c798557..ddeaef26ff2 100644 --- a/chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc +++ b/chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc @@ -14,6 +14,7 @@ #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/animation/element_animation.cc b/chromium/third_party/blink/renderer/core/animation/element_animation.cc index 0999d0082b5..4b2724b8d4f 100644 --- a/chromium/third_party/blink/renderer/core/animation/element_animation.cc +++ b/chromium/third_party/blink/renderer/core/animation/element_animation.cc @@ -28,12 +28,14 @@ namespace { void ReportFeaturePolicyViolationsIfNecessary( const Document& document, const KeyframeEffectModelBase& effect) { - if (document.IsFeatureEnabled(mojom::FeaturePolicyFeature::kLayoutAnimations)) - return; - for (const auto* blocked_property : - LayoutAnimationsPolicy::AffectedCSSProperties()) { - if (effect.Affects(PropertyHandle(*blocked_property))) - LayoutAnimationsPolicy::ReportViolation(*blocked_property, document); + for (const auto& property_handle : effect.Properties()) { + if (!property_handle.IsCSSProperty()) + continue; + const auto& css_property = property_handle.GetCSSProperty(); + if (LayoutAnimationsPolicy::AffectedCSSProperties().Contains( + &css_property)) { + LayoutAnimationsPolicy::ReportViolation(css_property, document); + } } } diff --git a/chromium/third_party/blink/renderer/core/animation/interpolation_effect.h b/chromium/third_party/blink/renderer/core/animation/interpolation_effect.h index 1b261ec0d4b..78cfee54a8a 100644 --- a/chromium/third_party/blink/renderer/core/animation/interpolation_effect.h +++ b/chromium/third_party/blink/renderer/core/animation/interpolation_effect.h @@ -39,7 +39,7 @@ class CORE_EXPORT InterpolationEffect double end, double apply_from, double apply_to) { - interpolations_.push_back(new InterpolationRecord( + interpolations_.push_back(MakeGarbageCollected<InterpolationRecord>( interpolation, std::move(easing), start, end, apply_from, apply_to)); } diff --git a/chromium/third_party/blink/renderer/core/animation/interpolation_effect_test.cc b/chromium/third_party/blink/renderer/core/animation/interpolation_effect_test.cc index 2c978b28da5..b7808c03833 100644 --- a/chromium/third_party/blink/renderer/core/animation/interpolation_effect_test.cc +++ b/chromium/third_party/blink/renderer/core/animation/interpolation_effect_test.cc @@ -40,7 +40,7 @@ Interpolation* CreateInterpolation(int from, int to) { TEST(AnimationInterpolationEffectTest, SingleInterpolation) { Persistent<InterpolationEffect> interpolation_effect = - new InterpolationEffect; + MakeGarbageCollected<InterpolationEffect>(); interpolation_effect->AddInterpolation( CreateInterpolation(0, 10), scoped_refptr<TimingFunction>(), 0, 1, -1, 2); @@ -71,7 +71,7 @@ TEST(AnimationInterpolationEffectTest, SingleInterpolation) { TEST(AnimationInterpolationEffectTest, MultipleInterpolations) { Persistent<InterpolationEffect> interpolation_effect = - new InterpolationEffect; + MakeGarbageCollected<InterpolationEffect>(); interpolation_effect->AddInterpolation( CreateInterpolation(10, 15), scoped_refptr<TimingFunction>(), 1, 2, 1, 3); interpolation_effect->AddInterpolation( diff --git a/chromium/third_party/blink/renderer/core/animation/invalidatable_interpolation.h b/chromium/third_party/blink/renderer/core/animation/invalidatable_interpolation.h index 5f7fdc569cc..5c60251616a 100644 --- a/chromium/third_party/blink/renderer/core/animation/invalidatable_interpolation.h +++ b/chromium/third_party/blink/renderer/core/animation/invalidatable_interpolation.h @@ -35,10 +35,22 @@ class CORE_EXPORT InvalidatableInterpolation : public Interpolation { const PropertyHandle& property, PropertySpecificKeyframe* start_keyframe, PropertySpecificKeyframe* end_keyframe) { - return new InvalidatableInterpolation(property, start_keyframe, - end_keyframe); + return MakeGarbageCollected<InvalidatableInterpolation>( + property, start_keyframe, end_keyframe); } + InvalidatableInterpolation(const PropertyHandle& property, + PropertySpecificKeyframe* start_keyframe, + PropertySpecificKeyframe* end_keyframe) + : Interpolation(), + property_(property), + interpolation_types_(nullptr), + interpolation_types_version_(0), + start_keyframe_(start_keyframe), + end_keyframe_(end_keyframe), + current_fraction_(std::numeric_limits<double>::quiet_NaN()), + is_conversion_cached_(false) {} + const PropertyHandle& GetProperty() const final { return property_; } void Interpolate(int iteration, double fraction) override; bool DependsOnUnderlyingValue() const final; @@ -58,18 +70,6 @@ class CORE_EXPORT InvalidatableInterpolation : public Interpolation { } private: - InvalidatableInterpolation(const PropertyHandle& property, - PropertySpecificKeyframe* start_keyframe, - PropertySpecificKeyframe* end_keyframe) - : Interpolation(), - property_(property), - interpolation_types_(nullptr), - interpolation_types_version_(0), - start_keyframe_(start_keyframe), - end_keyframe_(end_keyframe), - current_fraction_(std::numeric_limits<double>::quiet_NaN()), - is_conversion_cached_(false) {} - using ConversionCheckers = InterpolationType::ConversionCheckers; std::unique_ptr<TypedInterpolationValue> MaybeConvertUnderlyingValue( diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe.h b/chromium/third_party/blink/renderer/core/animation/keyframe.h index 909a4b61b6d..ccf93f6fb8d 100644 --- a/chromium/third_party/blink/renderer/core/animation/keyframe.h +++ b/chromium/third_party/blink/renderer/core/animation/keyframe.h @@ -120,6 +120,9 @@ class CORE_EXPORT Keyframe : public GarbageCollectedFinalized<Keyframe> { class CORE_EXPORT PropertySpecificKeyframe : public GarbageCollectedFinalized<PropertySpecificKeyframe> { public: + PropertySpecificKeyframe(double offset, + scoped_refptr<TimingFunction> easing, + EffectModel::CompositeOperation); virtual ~PropertySpecificKeyframe() = default; double Offset() const { return offset_; } TimingFunction& Easing() const { return *easing_; } @@ -159,10 +162,6 @@ class CORE_EXPORT Keyframe : public GarbageCollectedFinalized<Keyframe> { virtual void Trace(Visitor*){}; protected: - PropertySpecificKeyframe(double offset, - scoped_refptr<TimingFunction> easing, - EffectModel::CompositeOperation); - double offset_; scoped_refptr<TimingFunction> easing_; EffectModel::CompositeOperation composite_; diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc index 2c4e8d31b26..b291cf94ac8 100644 --- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc +++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc @@ -325,9 +325,11 @@ void KeyframeEffectModelBase::EnsureKeyframeGroups() const { KeyframeGroupMap::iterator group_iter = keyframe_groups_->find(property); PropertySpecificKeyframeGroup* group; if (group_iter == keyframe_groups_->end()) { - group = keyframe_groups_ - ->insert(property, new PropertySpecificKeyframeGroup) - .stored_value->value.Get(); + group = + keyframe_groups_ + ->insert(property, + MakeGarbageCollected<PropertySpecificKeyframeGroup>()) + .stored_value->value.Get(); } else { group = group_iter->value.Get(); } diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h index 3fe078e32a4..1d02dbd98db 100644 --- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h +++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h @@ -153,7 +153,7 @@ class CORE_EXPORT KeyframeEffectModelBase : public EffectModel { protected: KeyframeEffectModelBase(CompositeOperation composite, scoped_refptr<TimingFunction> default_keyframe_easing) - : interpolation_effect_(new InterpolationEffect), + : interpolation_effect_(MakeGarbageCollected<InterpolationEffect>()), last_iteration_(0), last_fraction_(std::numeric_limits<double>::quiet_NaN()), last_iteration_duration_(AnimationTimeDelta()), diff --git a/chromium/third_party/blink/renderer/core/animation/length_interpolation_functions.cc b/chromium/third_party/blink/renderer/core/animation/length_interpolation_functions.cc index b1cd14d943c..cbf455a28a0 100644 --- a/chromium/third_party/blink/renderer/core/animation/length_interpolation_functions.cc +++ b/chromium/third_party/blink/renderer/core/animation/length_interpolation_functions.cc @@ -190,9 +190,11 @@ Length LengthInterpolationFunctions::CreateLength( if (percentage != 0) has_percentage = true; - if (pixels != 0 && has_percentage) - return Length( - CalculationValue::Create(PixelsAndPercent(pixels, percentage), range)); + if (pixels != 0 && has_percentage) { + return Length(CalculationValue::Create( + PixelsAndPercent(clampTo<float>(pixels), clampTo<float>(percentage)), + range)); + } if (has_percentage) return Length(ClampToRange(percentage, range), kPercent); return Length( diff --git a/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc b/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc index 527c9e8f47a..d049473f14b 100644 --- a/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc +++ b/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc @@ -10,6 +10,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/animation/css_number_interpolation_type.h" #include "third_party/blink/renderer/core/animation/interpolation_value.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc index 394c242f7f2..63868fca81a 100644 --- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc +++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc @@ -65,8 +65,10 @@ bool StringToScrollOffset(String scroll_offset, CSSPrimitiveValue** result) { Node* ResolveScrollSource(Element* scroll_source) { // When in quirks mode we need the style to be clean, so we don't use // |ScrollingElementNoLayout|. - if (scroll_source == scroll_source->GetDocument().scrollingElement()) + if (scroll_source && + scroll_source == scroll_source->GetDocument().scrollingElement()) { return &scroll_source->GetDocument(); + } return scroll_source; } } // namespace @@ -122,14 +124,16 @@ ScrollTimeline::ScrollTimeline(Element* scroll_source, start_scroll_offset_(start_scroll_offset), end_scroll_offset_(end_scroll_offset), time_range_(time_range) { - DCHECK(scroll_source_); } double ScrollTimeline::currentTime(bool& is_null) { is_null = true; - // 1. If scrollSource does not currently have a CSS layout box, or if its - // layout box is not a scroll container, return an unresolved time value. - LayoutBox* layout_box = resolved_scroll_source_->GetLayoutBox(); + + // 1. If scrollSource is null, does not currently have a CSS layout box, or if + // its layout box is not a scroll container, return an unresolved time value. + LayoutBox* layout_box = resolved_scroll_source_ + ? resolved_scroll_source_->GetLayoutBox() + : nullptr; if (!layout_box || !layout_box->HasOverflowClip()) { return std::numeric_limits<double>::quiet_NaN(); } @@ -291,6 +295,9 @@ void ScrollTimeline::ResolveScrollStartAndEnd( } void ScrollTimeline::AttachAnimation() { + if (!resolved_scroll_source_) + return; + GetActiveScrollTimelineSet().insert(resolved_scroll_source_); if (resolved_scroll_source_->IsElementNode()) ToElement(resolved_scroll_source_)->SetNeedsCompositingUpdate(); @@ -306,6 +313,9 @@ void ScrollTimeline::AttachAnimation() { } void ScrollTimeline::DetachAnimation() { + if (!resolved_scroll_source_) + return; + GetActiveScrollTimelineSet().erase(resolved_scroll_source_); if (resolved_scroll_source_->IsElementNode()) ToElement(resolved_scroll_source_)->SetNeedsCompositingUpdate(); diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h index ee43c4539c9..a78393c25c8 100644 --- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h +++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h @@ -58,8 +58,10 @@ class CORE_EXPORT ScrollTimeline final : public AnimationTimeline { // Returns the Node that should actually have the ScrollableArea (if one // exists). This can differ from |scrollSource| when |scroll_source_| is the - // Document's scrollingElement. + // Document's scrollingElement, and it may be null if the document was removed + // before the ScrollTimeline was created. Node* ResolvedScrollSource() const { return resolved_scroll_source_; } + ScrollDirection GetOrientation() const { return orientation_; } void GetCurrentAndMaxOffset(const LayoutBox*, diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl index 0f518d2e4d6..74e907227c7 100644 --- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl +++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_options.idl @@ -14,7 +14,7 @@ enum ScrollDirection { enum ScrollTimelineAutoKeyword { "auto" }; dictionary ScrollTimelineOptions { - Element scrollSource; + Element? scrollSource = null; ScrollDirection orientation = "block"; DOMString startScrollOffset = "auto"; DOMString endScrollOffset = "auto"; diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc index 5de8c38bf37..0ea4dcba6c0 100644 --- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc +++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc @@ -220,4 +220,24 @@ TEST_F(ScrollTimelineTest, EXPECT_EQ(&GetDocument(), scroll_timeline->ResolvedScrollSource()); } +TEST_F(ScrollTimelineTest, AttachOrDetachAnimationWithNullScrollSource) { + // Directly call the constructor to make it easier to pass a null + // scrollSource. The alternative approach would require us to remove the + // documentElement from the document. + Element* scroll_source = nullptr; + CSSPrimitiveValue* start_scroll_offset = nullptr; + CSSPrimitiveValue* end_scroll_offset = nullptr; + ScrollTimeline* scroll_timeline = MakeGarbageCollected<ScrollTimeline>( + scroll_source, ScrollTimeline::Block, start_scroll_offset, + end_scroll_offset, 100); + + // Sanity checks. + ASSERT_EQ(scroll_timeline->scrollSource(), nullptr); + ASSERT_EQ(scroll_timeline->ResolvedScrollSource(), nullptr); + + // These calls should be no-ops in this mode, and shouldn't crash. + scroll_timeline->AttachAnimation(); + scroll_timeline->DetachAnimation(); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc new file mode 100644 index 00000000000..c9667a02f43 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.cc @@ -0,0 +1,119 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/animation/scroll_timeline_util.h" + +#include "third_party/blink/renderer/bindings/core/v8/double_or_scroll_timeline_auto_keyword.h" +#include "third_party/blink/renderer/core/animation/animation_timeline.h" +#include "third_party/blink/renderer/core/dom/node.h" +#include "third_party/blink/renderer/core/layout/layout_box.h" +#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h" + +namespace blink { + +namespace scroll_timeline_util { + +std::unique_ptr<CompositorScrollTimeline> ToCompositorScrollTimeline( + AnimationTimeline* timeline) { + if (!timeline || timeline->IsDocumentTimeline()) + return nullptr; + + ScrollTimeline* scroll_timeline = ToScrollTimeline(timeline); + Node* scroll_source = scroll_timeline->ResolvedScrollSource(); + base::Optional<CompositorElementId> element_id = + GetCompositorScrollElementId(scroll_source); + + DoubleOrScrollTimelineAutoKeyword time_range; + scroll_timeline->timeRange(time_range); + // TODO(smcgruer): Handle 'auto' time range value. + DCHECK(time_range.IsDouble()); + + LayoutBox* box = scroll_source ? scroll_source->GetLayoutBox() : nullptr; + + CompositorScrollTimeline::ScrollDirection orientation = ConvertOrientation( + scroll_timeline->GetOrientation(), box ? box->Style() : nullptr); + + base::Optional<double> start_scroll_offset; + base::Optional<double> end_scroll_offset; + if (box) { + double current_offset; + double max_offset; + scroll_timeline->GetCurrentAndMaxOffset(box, current_offset, max_offset); + + double resolved_start_scroll_offset = 0; + double resolved_end_scroll_offset = max_offset; + scroll_timeline->ResolveScrollStartAndEnd(box, max_offset, + resolved_start_scroll_offset, + resolved_end_scroll_offset); + start_scroll_offset = resolved_start_scroll_offset; + end_scroll_offset = resolved_end_scroll_offset; + } + + return std::make_unique<CompositorScrollTimeline>( + element_id, orientation, start_scroll_offset, end_scroll_offset, + time_range.GetAsDouble()); +} + +base::Optional<CompositorElementId> GetCompositorScrollElementId( + const Node* node) { + if (!node || !node->GetLayoutObject() || !node->GetLayoutObject()->UniqueId()) + return base::nullopt; + return CompositorElementIdFromUniqueObjectId( + node->GetLayoutObject()->UniqueId(), + CompositorElementIdNamespace::kScroll); +} + +// The compositor does not know about writing modes, so we have to convert the +// web concepts of 'block' and 'inline' direction into absolute vertical or +// horizontal directions. +CompositorScrollTimeline::ScrollDirection ConvertOrientation( + ScrollTimeline::ScrollDirection orientation, + const ComputedStyle* style) { + // Easy cases; physical is always physical. + if (orientation == ScrollTimeline::Horizontal) + return CompositorScrollTimeline::ScrollRight; + if (orientation == ScrollTimeline::Vertical) + return CompositorScrollTimeline::ScrollDown; + + // Harder cases; first work out which axis is which, and then for each check + // which edge we start at. + + // writing-mode: horizontal-tb + bool is_horizontal_writing_mode = + style ? style->IsHorizontalWritingMode() : true; + // writing-mode: vertical-lr + bool is_flipped_lines_writing_mode = + style ? style->IsFlippedLinesWritingMode() : false; + // direction: ltr; + bool is_ltr_direction = style ? style->IsLeftToRightDirection() : true; + + if (orientation == ScrollTimeline::Block) { + if (is_horizontal_writing_mode) { + // For horizontal writing mode, block is vertical. The starting edge is + // always the top. + return CompositorScrollTimeline::ScrollDown; + } + // For vertical writing mode, the block axis is horizontal. The starting + // edge depends on if we are lr or rl. + return is_flipped_lines_writing_mode ? CompositorScrollTimeline::ScrollRight + : CompositorScrollTimeline::ScrollLeft; + } + + DCHECK_EQ(orientation, ScrollTimeline::Inline); + if (is_horizontal_writing_mode) { + // For horizontal writing mode, inline is horizontal. The starting edge + // depends on the directionality. + return is_ltr_direction ? CompositorScrollTimeline::ScrollRight + : CompositorScrollTimeline::ScrollLeft; + } + // For vertical writing mode, inline is vertical. The starting edge still + // depends on the directionality; whether it is vertical-lr or vertical-rl + // does not matter. + return is_ltr_direction ? CompositorScrollTimeline::ScrollDown + : CompositorScrollTimeline::ScrollUp; +} + +} // namespace scroll_timeline_util + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.h b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.h new file mode 100644 index 00000000000..a1111278ccd --- /dev/null +++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util.h @@ -0,0 +1,44 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_UTIL_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_UTIL_H_ + +#include <memory> + +#include "base/optional.h" +#include "third_party/blink/renderer/core/animation/scroll_timeline.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/animation/compositor_animation.h" + +namespace blink { + +class AnimationTimeline; +class ComputedStyle; +class Node; + +namespace scroll_timeline_util { + +// Converts the input timeline to the compositor representation of a +// ScrollTimeline. Returns nullptr if the input is not a ScrollTimeline. +std::unique_ptr<CompositorScrollTimeline> CORE_EXPORT +ToCompositorScrollTimeline(AnimationTimeline*); + +// Retrieves the 'scroll' compositor element id for the input node, or +// base::nullopt if it does not exist. +base::Optional<CompositorElementId> CORE_EXPORT +GetCompositorScrollElementId(const Node*); + +// Convert the blink concept of a ScrollTimeline orientation into the cc one. +// +// This implements a subset of the conversions documented in +// https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical +CompositorScrollTimeline::ScrollDirection CORE_EXPORT +ConvertOrientation(ScrollTimeline::ScrollDirection, const ComputedStyle*); + +} // namespace scroll_timeline_util + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SCROLL_TIMELINE_UTIL_H_ diff --git a/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc new file mode 100644 index 00000000000..cd0ec23e17c --- /dev/null +++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline_util_test.cc @@ -0,0 +1,220 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/animation/scroll_timeline_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/animation/document_timeline.h" +#include "third_party/blink/renderer/core/html/html_div_element.h" +#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" + +namespace blink { + +namespace scroll_timeline_util { + +using ScrollTimelineUtilTest = PageTestBase; + +// This test covers only the basic conversions for element id, time range, +// orientation, and start and end scroll offset. Complex orientation conversions +// are tested in the GetOrientation* tests, and complex start/end scroll offset +// resolutions are tested in blink::ScrollTimelineTest. +TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimeline) { + SetBodyInnerHTML(R"HTML( + <style> + #scroller { + overflow: auto; + width: 100px; + height: 100px; + } + #contents { + height: 1000px; + } + </style> + <div id='scroller'><div id='contents'></div></div> + )HTML"); + + Element* scroller = GetElementById("scroller"); + base::Optional<CompositorElementId> element_id = + GetCompositorScrollElementId(scroller); + ASSERT_TRUE(element_id.has_value()); + + ScrollTimelineOptions* options = ScrollTimelineOptions::Create(); + options->setScrollSource(scroller); + const double time_range = 100; + options->setTimeRange( + DoubleOrScrollTimelineAutoKeyword::FromDouble(time_range)); + options->setOrientation("block"); + options->setStartScrollOffset("50px"); + options->setEndScrollOffset("auto"); + ScrollTimeline* timeline = + ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION); + + std::unique_ptr<CompositorScrollTimeline> compositor_timeline = + ToCompositorScrollTimeline(timeline); + EXPECT_EQ(compositor_timeline->GetActiveIdForTest(), base::nullopt); + EXPECT_EQ(compositor_timeline->GetPendingIdForTest(), element_id); + EXPECT_EQ(compositor_timeline->GetTimeRangeForTest(), time_range); + EXPECT_EQ(compositor_timeline->GetDirectionForTest(), + CompositorScrollTimeline::ScrollDown); + EXPECT_EQ(compositor_timeline->GetStartScrollOffsetForTest(), 50); + // 900 is contents-size - scroller-viewport == 1000 - 100 + EXPECT_EQ(compositor_timeline->GetEndScrollOffsetForTest(), 900); +} + +TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimelineNullParameter) { + EXPECT_EQ(ToCompositorScrollTimeline(nullptr), nullptr); +} + +TEST_F(ScrollTimelineUtilTest, + ToCompositorScrollTimelineDocumentTimelineParameter) { + DocumentTimeline* timeline = + DocumentTimeline::Create(Document::CreateForTest()); + EXPECT_EQ(ToCompositorScrollTimeline(timeline), nullptr); +} + +TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimelineNullScrollSource) { + // Directly call the constructor to make it easier to pass a null + // scrollSource. The alternative approach would require us to remove the + // documentElement from the document. + Element* scroll_source = nullptr; + CSSPrimitiveValue* start_scroll_offset = nullptr; + CSSPrimitiveValue* end_scroll_offset = nullptr; + ScrollTimeline* timeline = MakeGarbageCollected<ScrollTimeline>( + scroll_source, ScrollTimeline::Block, start_scroll_offset, + end_scroll_offset, 100); + + std::unique_ptr<CompositorScrollTimeline> compositor_timeline = + ToCompositorScrollTimeline(timeline); + ASSERT_TRUE(compositor_timeline.get()); + EXPECT_EQ(compositor_timeline->GetPendingIdForTest(), base::nullopt); +} + +TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimelineNullLayoutBox) { + Element* div = HTMLDivElement::Create(GetDocument()); + ASSERT_FALSE(div->GetLayoutBox()); + + ScrollTimelineOptions* options = ScrollTimelineOptions::Create(); + DoubleOrScrollTimelineAutoKeyword time_range = + DoubleOrScrollTimelineAutoKeyword::FromDouble(100); + options->setTimeRange(time_range); + options->setScrollSource(div); + ScrollTimeline* timeline = + ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION); + + std::unique_ptr<CompositorScrollTimeline> compositor_timeline = + ToCompositorScrollTimeline(timeline); + EXPECT_TRUE(compositor_timeline.get()); + // Here we just want to test the start/end scroll offset. + // ToCompositorScrollTimelineNullScrollSource covers the expected pending id + // and ConvertOrientationNullStyle covers the orientation conversion. + EXPECT_EQ(compositor_timeline->GetStartScrollOffsetForTest(), base::nullopt); + EXPECT_EQ(compositor_timeline->GetEndScrollOffsetForTest(), base::nullopt); +} + +TEST_F(ScrollTimelineUtilTest, ConvertOrientationPhysicalCases) { + // For physical the writing-mode and directionality shouldn't matter, so make + // sure it doesn't. + Vector<WritingMode> writing_modes = {WritingMode::kHorizontalTb, + WritingMode::kVerticalLr, + WritingMode::kVerticalRl}; + Vector<TextDirection> directions = {TextDirection::kLtr, TextDirection::kRtl}; + + scoped_refptr<ComputedStyle> style = ComputedStyle::Create(); + for (const WritingMode& writing_mode : writing_modes) { + for (const TextDirection& direction : directions) { + style->SetWritingMode(writing_mode); + style->SetDirection(direction); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Vertical, style.get()), + CompositorScrollTimeline::ScrollDown); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Horizontal, style.get()), + CompositorScrollTimeline::ScrollRight); + } + } +} + +TEST_F(ScrollTimelineUtilTest, ConvertOrientationLogical) { + scoped_refptr<ComputedStyle> style = ComputedStyle::Create(); + + // horizontal-tb, ltr + style->SetWritingMode(WritingMode::kHorizontalTb); + style->SetDirection(TextDirection::kLtr); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Block, style.get()), + CompositorScrollTimeline::ScrollDown); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Inline, style.get()), + CompositorScrollTimeline::ScrollRight); + + // vertical-lr, ltr + style->SetWritingMode(WritingMode::kVerticalLr); + style->SetDirection(TextDirection::kLtr); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Block, style.get()), + CompositorScrollTimeline::ScrollRight); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Inline, style.get()), + CompositorScrollTimeline::ScrollDown); + + // vertical-rl, ltr + style->SetWritingMode(WritingMode::kVerticalRl); + style->SetDirection(TextDirection::kLtr); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Block, style.get()), + CompositorScrollTimeline::ScrollLeft); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Inline, style.get()), + CompositorScrollTimeline::ScrollDown); + + // horizontal-tb, rtl + style->SetWritingMode(WritingMode::kHorizontalTb); + style->SetDirection(TextDirection::kRtl); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Block, style.get()), + CompositorScrollTimeline::ScrollDown); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Inline, style.get()), + CompositorScrollTimeline::ScrollLeft); + + // vertical-lr, rtl + style->SetWritingMode(WritingMode::kVerticalLr); + style->SetDirection(TextDirection::kRtl); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Block, style.get()), + CompositorScrollTimeline::ScrollRight); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Inline, style.get()), + CompositorScrollTimeline::ScrollUp); + + // vertical-rl, rtl + style->SetWritingMode(WritingMode::kVerticalRl); + style->SetDirection(TextDirection::kRtl); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Block, style.get()), + CompositorScrollTimeline::ScrollLeft); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Inline, style.get()), + CompositorScrollTimeline::ScrollUp); +} + +TEST_F(ScrollTimelineUtilTest, ConvertOrientationNullStyle) { + // When the style is nullptr we assume horizontal-tb and ltr direction. This + // means that block is ScrollDown and inline is ScrollRight + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Vertical, nullptr), + CompositorScrollTimeline::ScrollDown); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Horizontal, nullptr), + CompositorScrollTimeline::ScrollRight); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Block, nullptr), + CompositorScrollTimeline::ScrollDown); + EXPECT_EQ(ConvertOrientation(ScrollTimeline::Inline, nullptr), + CompositorScrollTimeline::ScrollRight); +} + +TEST_F(ScrollTimelineUtilTest, GetCompositorScrollElementIdNullNode) { + EXPECT_EQ(GetCompositorScrollElementId(nullptr), base::nullopt); +} + +TEST_F(ScrollTimelineUtilTest, GetCompositorScrollElementIdNullLayoutObject) { + Element* div = HTMLDivElement::Create(GetDocument()); + ASSERT_FALSE(div->GetLayoutObject()); + EXPECT_EQ(GetCompositorScrollElementId(nullptr), base::nullopt); +} + +TEST_F(ScrollTimelineUtilTest, GetCompositorScrollElementIdNoUniqueId) { + SetBodyInnerHTML("<div id='test'></div>"); + Element* test = GetElementById("test"); + ASSERT_TRUE(test->GetLayoutObject()); + ASSERT_FALSE(test->GetLayoutObject()->UniqueId()); + EXPECT_EQ(GetCompositorScrollElementId(test), base::nullopt); +} + +} // namespace scroll_timeline_util + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc b/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc index ff3c9c12c60..d696d002dee 100644 --- a/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc +++ b/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc @@ -141,7 +141,7 @@ void StringKeyframe::Trace(Visitor* visitor) { } Keyframe* StringKeyframe::Clone() const { - return new StringKeyframe(*this); + return MakeGarbageCollected<StringKeyframe>(*this); } Keyframe::PropertySpecificKeyframe* diff --git a/chromium/third_party/blink/renderer/core/animation/string_keyframe.h b/chromium/third_party/blink/renderer/core/animation/string_keyframe.h index d2b824f200c..b8847abae4a 100644 --- a/chromium/third_party/blink/renderer/core/animation/string_keyframe.h +++ b/chromium/third_party/blink/renderer/core/animation/string_keyframe.h @@ -27,7 +27,16 @@ class StyleSheetContents; // expand shorthand properties; that is done for computed keyframes. class CORE_EXPORT StringKeyframe : public Keyframe { public: - static StringKeyframe* Create() { return new StringKeyframe; } + static StringKeyframe* Create() { + return MakeGarbageCollected<StringKeyframe>(); + } + + StringKeyframe() + : css_property_map_( + MutableCSSPropertyValueSet::Create(kHTMLStandardMode)), + presentation_attribute_map_( + MutableCSSPropertyValueSet::Create(kHTMLStandardMode)) {} + StringKeyframe(const StringKeyframe& copy_from); MutableCSSPropertyValueSet::SetResult SetCSSPropertyValue( const AtomicString& property_name, @@ -88,10 +97,19 @@ class CORE_EXPORT StringKeyframe : public Keyframe { scoped_refptr<TimingFunction> easing, const CSSValue* value, EffectModel::CompositeOperation composite) { - return new CSSPropertySpecificKeyframe(offset, std::move(easing), value, - composite); + return MakeGarbageCollected<CSSPropertySpecificKeyframe>( + offset, std::move(easing), value, composite); } + CSSPropertySpecificKeyframe(double offset, + scoped_refptr<TimingFunction> easing, + const CSSValue* value, + EffectModel::CompositeOperation composite) + : Keyframe::PropertySpecificKeyframe(offset, + std::move(easing), + composite), + value_(value) {} + const CSSValue* Value() const { return value_.Get(); } bool PopulateAnimatableValue(const PropertyHandle&, @@ -110,15 +128,6 @@ class CORE_EXPORT StringKeyframe : public Keyframe { void Trace(Visitor*) override; private: - CSSPropertySpecificKeyframe(double offset, - scoped_refptr<TimingFunction> easing, - const CSSValue* value, - EffectModel::CompositeOperation composite) - : Keyframe::PropertySpecificKeyframe(offset, - std::move(easing), - composite), - value_(value) {} - Keyframe::PropertySpecificKeyframe* CloneWithOffset( double offset) const override; bool IsCSSPropertySpecificKeyframe() const override { return true; } @@ -135,10 +144,19 @@ class CORE_EXPORT StringKeyframe : public Keyframe { scoped_refptr<TimingFunction> easing, const String& value, EffectModel::CompositeOperation composite) { - return new SVGPropertySpecificKeyframe(offset, std::move(easing), value, - composite); + return MakeGarbageCollected<SVGPropertySpecificKeyframe>( + offset, std::move(easing), value, composite); } + SVGPropertySpecificKeyframe(double offset, + scoped_refptr<TimingFunction> easing, + const String& value, + EffectModel::CompositeOperation composite) + : Keyframe::PropertySpecificKeyframe(offset, + std::move(easing), + composite), + value_(value) {} + const String& Value() const { return value_; } PropertySpecificKeyframe* CloneWithOffset(double offset) const final; @@ -151,30 +169,12 @@ class CORE_EXPORT StringKeyframe : public Keyframe { scoped_refptr<TimingFunction> easing) const final; private: - SVGPropertySpecificKeyframe(double offset, - scoped_refptr<TimingFunction> easing, - const String& value, - EffectModel::CompositeOperation composite) - : Keyframe::PropertySpecificKeyframe(offset, - std::move(easing), - composite), - value_(value) {} - bool IsSVGPropertySpecificKeyframe() const override { return true; } String value_; }; - protected: - StringKeyframe() - : css_property_map_( - MutableCSSPropertyValueSet::Create(kHTMLStandardMode)), - presentation_attribute_map_( - MutableCSSPropertyValueSet::Create(kHTMLStandardMode)) {} - private: - StringKeyframe(const StringKeyframe& copy_from); - Keyframe* Clone() const override; Keyframe::PropertySpecificKeyframe* CreatePropertySpecificKeyframe( const PropertyHandle&, diff --git a/chromium/third_party/blink/renderer/core/animation/timing_calculations.h b/chromium/third_party/blink/renderer/core/animation/timing_calculations.h index 396a0cf0ae8..db759dc2e59 100644 --- a/chromium/third_party/blink/renderer/core/animation/timing_calculations.h +++ b/chromium/third_party/blink/renderer/core/animation/timing_calculations.h @@ -50,18 +50,31 @@ static inline double MultiplyZeroAlwaysGivesZero(AnimationTimeDelta x, return x.is_zero() || y == 0 ? 0 : (x * y).InSecondsF(); } -static inline AnimationEffect::Phase CalculatePhase(double active_duration, - double local_time, - const Timing& specified) { +// https://drafts.csswg.org/web-animations-1/#animation-effect-phases-and-states +static inline AnimationEffect::Phase CalculatePhase( + double active_duration, + double local_time, + AnimationEffect::AnimationDirection direction, + const Timing& specified) { DCHECK_GE(active_duration, 0); if (IsNull(local_time)) return AnimationEffect::kPhaseNone; - double end_time = - specified.start_delay + active_duration + specified.end_delay; - if (local_time < std::min(specified.start_delay, end_time)) + double end_time = std::max( + specified.start_delay + active_duration + specified.end_delay, 0.0); + double before_active_boundary_time = + std::max(std::min(specified.start_delay, end_time), 0.0); + if (local_time < before_active_boundary_time || + (local_time == before_active_boundary_time && + direction == AnimationEffect::AnimationDirection::kBackwards)) { return AnimationEffect::kPhaseBefore; - if (local_time >= std::min(specified.start_delay + active_duration, end_time)) + } + double active_after_boundary_time = std::max( + std::min(specified.start_delay + active_duration, end_time), 0.0); + if (local_time > active_after_boundary_time || + (local_time == active_after_boundary_time && + direction == AnimationEffect::AnimationDirection::kForwards)) { return AnimationEffect::kPhaseAfter; + } return AnimationEffect::kPhaseActive; } @@ -89,13 +102,12 @@ static inline double CalculateActiveTime(double active_duration, AnimationEffect::Phase phase, const Timing& specified) { DCHECK_GE(active_duration, 0); - DCHECK_EQ(phase, CalculatePhase(active_duration, local_time, specified)); switch (phase) { case AnimationEffect::kPhaseBefore: if (fill_mode == Timing::FillMode::BACKWARDS || fill_mode == Timing::FillMode::BOTH) - return 0; + return std::max(local_time - specified.start_delay, 0.0); return NullValue(); case AnimationEffect::kPhaseActive: if (IsActiveInParentPhase(parent_phase, fill_mode)) @@ -103,9 +115,10 @@ static inline double CalculateActiveTime(double active_duration, return NullValue(); case AnimationEffect::kPhaseAfter: if (fill_mode == Timing::FillMode::FORWARDS || - fill_mode == Timing::FillMode::BOTH) - return std::max(0.0, std::min(active_duration, - active_duration + specified.end_delay)); + fill_mode == Timing::FillMode::BOTH) { + return std::max( + 0.0, std::min(active_duration, local_time - specified.start_delay)); + } return NullValue(); case AnimationEffect::kPhaseNone: DCHECK(IsNull(local_time)); diff --git a/chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc b/chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc index 8e6ea85070f..116b427c632 100644 --- a/chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc +++ b/chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc @@ -55,6 +55,10 @@ TEST(AnimationTimingCalculationsTest, ActiveTime) { EXPECT_EQ(0, CalculateActiveTime(20, Timing::FillMode::BOTH, 0, AnimationEffect::kPhaseActive, AnimationEffect::kPhaseBefore, timing)); + timing.start_delay = -10; + EXPECT_EQ(5, CalculateActiveTime(20, Timing::FillMode::BACKWARDS, -5, + AnimationEffect::kPhaseActive, + AnimationEffect::kPhaseBefore, timing)); // Active Phase timing.start_delay = 10; diff --git a/chromium/third_party/blink/renderer/core/animation/transition_interpolation.h b/chromium/third_party/blink/renderer/core/animation/transition_interpolation.h index 2eba87a952f..2ebada4f8c1 100644 --- a/chromium/third_party/blink/renderer/core/animation/transition_interpolation.h +++ b/chromium/third_party/blink/renderer/core/animation/transition_interpolation.h @@ -45,30 +45,11 @@ class CORE_EXPORT TransitionInterpolation : public Interpolation { InterpolationValue&& end, AnimatableValue* compositor_start, AnimatableValue* compositor_end) { - return new TransitionInterpolation(property, type, std::move(start), - std::move(end), compositor_start, - compositor_end); + return MakeGarbageCollected<TransitionInterpolation>( + property, type, std::move(start), std::move(end), compositor_start, + compositor_end); } - void Apply(StyleResolverState&) const; - - bool IsTransitionInterpolation() const final { return true; } - - const PropertyHandle& GetProperty() const final { return property_; } - - std::unique_ptr<TypedInterpolationValue> GetInterpolatedValue() const; - - AnimatableValue* GetInterpolatedCompositorValue() const; - - void Interpolate(int iteration, double fraction) final; - - void Trace(Visitor* visitor) override { - visitor->Trace(compositor_start_); - visitor->Trace(compositor_end_); - Interpolation::Trace(visitor); - } - - protected: TransitionInterpolation(const PropertyHandle& property, const InterpolationType& type, InterpolationValue&& start, @@ -95,6 +76,24 @@ class CORE_EXPORT TransitionInterpolation : public Interpolation { property_.GetCSSProperty().IsCompositableProperty()); } + void Apply(StyleResolverState&) const; + + bool IsTransitionInterpolation() const final { return true; } + + const PropertyHandle& GetProperty() const final { return property_; } + + std::unique_ptr<TypedInterpolationValue> GetInterpolatedValue() const; + + AnimatableValue* GetInterpolatedCompositorValue() const; + + void Interpolate(int iteration, double fraction) final; + + void Trace(Visitor* visitor) override { + visitor->Trace(compositor_start_); + visitor->Trace(compositor_end_); + Interpolation::Trace(visitor); + } + private: const InterpolableValue& CurrentInterpolableValue() const; NonInterpolableValue* CurrentNonInterpolableValue() const; diff --git a/chromium/third_party/blink/renderer/core/animation/transition_keyframe.h b/chromium/third_party/blink/renderer/core/animation/transition_keyframe.h index 768bdf86899..768f9a73f9f 100644 --- a/chromium/third_party/blink/renderer/core/animation/transition_keyframe.h +++ b/chromium/third_party/blink/renderer/core/animation/transition_keyframe.h @@ -22,8 +22,16 @@ class CORE_EXPORT TransitionKeyframe : public Keyframe { public: static TransitionKeyframe* Create(const PropertyHandle& property) { DCHECK(!property.IsSVGAttribute()); - return new TransitionKeyframe(property); + return MakeGarbageCollected<TransitionKeyframe>(property); } + + TransitionKeyframe(const PropertyHandle& property) : property_(property) {} + TransitionKeyframe(const TransitionKeyframe& copy_from) + : Keyframe(copy_from.offset_, copy_from.composite_, copy_from.easing_), + property_(copy_from.property_), + value_(copy_from.value_->Clone()), + compositor_value_(copy_from.compositor_value_) {} + void SetValue(std::unique_ptr<TypedInterpolationValue> value) { // Speculative CHECK to help investigate crbug.com/826627. The theory is // that |SetValue| is being called with a |value| that has no underlying @@ -48,10 +56,22 @@ class CORE_EXPORT TransitionKeyframe : public Keyframe { EffectModel::CompositeOperation composite, std::unique_ptr<TypedInterpolationValue> value, AnimatableValue* compositor_value) { - return new PropertySpecificKeyframe(offset, std::move(easing), composite, - std::move(value), compositor_value); + return MakeGarbageCollected<PropertySpecificKeyframe>( + offset, std::move(easing), composite, std::move(value), + compositor_value); } + PropertySpecificKeyframe(double offset, + scoped_refptr<TimingFunction> easing, + EffectModel::CompositeOperation composite, + std::unique_ptr<TypedInterpolationValue> value, + AnimatableValue* compositor_value) + : Keyframe::PropertySpecificKeyframe(offset, + std::move(easing), + composite), + value_(std::move(value)), + compositor_value_(compositor_value) {} + const AnimatableValue* GetAnimatableValue() const final { return compositor_value_; } @@ -72,17 +92,6 @@ class CORE_EXPORT TransitionKeyframe : public Keyframe { void Trace(Visitor*) override; private: - PropertySpecificKeyframe(double offset, - scoped_refptr<TimingFunction> easing, - EffectModel::CompositeOperation composite, - std::unique_ptr<TypedInterpolationValue> value, - AnimatableValue* compositor_value) - : Keyframe::PropertySpecificKeyframe(offset, - std::move(easing), - composite), - value_(std::move(value)), - compositor_value_(compositor_value) {} - Keyframe::PropertySpecificKeyframe* CloneWithOffset( double offset) const final { return Create(offset, easing_, composite_, value_->Clone(), @@ -94,17 +103,11 @@ class CORE_EXPORT TransitionKeyframe : public Keyframe { }; private: - TransitionKeyframe(const PropertyHandle& property) : property_(property) {} - - TransitionKeyframe(const TransitionKeyframe& copy_from) - : Keyframe(copy_from.offset_, copy_from.composite_, copy_from.easing_), - property_(copy_from.property_), - value_(copy_from.value_->Clone()), - compositor_value_(copy_from.compositor_value_) {} - bool IsTransitionKeyframe() const final { return true; } - Keyframe* Clone() const final { return new TransitionKeyframe(*this); } + Keyframe* Clone() const final { + return MakeGarbageCollected<TransitionKeyframe>(*this); + } Keyframe::PropertySpecificKeyframe* CreatePropertySpecificKeyframe( const PropertyHandle&, diff --git a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc index fc280aa2e75..4b73d0a4fd9 100644 --- a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc +++ b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc @@ -110,6 +110,19 @@ WorkletAnimationController::EnsureMainThreadMutatorDispatcher( return mutator_dispatcher; } +// TODO(yigu): Currently one animator name is synced back per registration. +// Eventually all registered names should be synced in batch once a module +// completes its loading in the worklet scope. https://crbug.com/920722. +void WorkletAnimationController::SynchronizeAnimatorName( + const String& animator_name) { + animator_names_.insert(animator_name); +} + +bool WorkletAnimationController::IsAnimatorRegistered( + const String& animator_name) const { + return animator_names_.Contains(animator_name); +} + void WorkletAnimationController::SetMutationUpdate( std::unique_ptr<AnimationWorkletOutput> output_state) { if (!output_state) @@ -126,7 +139,8 @@ void WorkletAnimationController::MutateAnimations() { if (!main_thread_mutator_client_) return; - main_thread_mutator_client_->Mutator()->Mutate(CollectAnimationStates()); + main_thread_mutator_client_->Mutator()->MutateSynchronously( + CollectAnimationStates()); } std::unique_ptr<AnimationWorkletDispatcherInput> diff --git a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h index a20ebe8c28d..3b9bdb7774b 100644 --- a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h +++ b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h @@ -55,8 +55,17 @@ class CORE_EXPORT WorkletAnimationController base::WeakPtr<AnimationWorkletMutatorDispatcherImpl> EnsureMainThreadMutatorDispatcher( scoped_refptr<base::SingleThreadTaskRunner>* mutator_task_runner); + void SetMutationUpdate( std::unique_ptr<AnimationWorkletOutput> output) override; + void NotifyAnimationsPending() override {} + void NotifyAnimationsReady() override {} + + void SynchronizeAnimatorName(const String& animator_name) override; + // Returns true if the animator with given name is registered in + // AnimationWorkletGlobalScope. + bool IsAnimatorRegistered(const String& animator_name) const; + void Trace(blink::Visitor*); private: @@ -67,6 +76,8 @@ class CORE_EXPORT WorkletAnimationController HeapHashSet<Member<WorkletAnimationBase>> pending_animations_; HeapHashMap<int, Member<WorkletAnimationBase>> animations_; + WTF::HashSet<String> animator_names_; + // TODO(yigu): The following proxy is needed for platform/ to access this // class. We should bypass it eventually. std::unique_ptr<MainThreadMutatorClient> main_thread_mutator_client_; |