Commit 153f3a5a authored by Anders Hartvoll Ruud's avatar Anders Hartvoll Ruud Committed by Commit Bot

[scroll-animations] Introduce CSSScrollTimeline

This CL adds CSSScrollTimeline, which is like a regular ScrollTimeline
except it originates from an @scroll-timeline rule. For now, the
CSSScrollTimeline doesn't do anything beyond what ScrollTimeline
does, but in the future CSSScrollTimelines will contain additional
information needed to invalidate attached Animations when
@scroll-timelines, the computed value of animation-timeline, or
other circumstances change.

All the Compute* utilities have been moved to css_scroll_timeline.cc
without any changes. In general this CL is a pure refactor, and should
have no behavior change.

Bug: 1074052
Change-Id: I42291cc5fda4d8386c37803a3bf461c007fb5198
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2374646
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: default avatarKevin Ellis <kevers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#801440}
parent 3f9db733
...@@ -60,6 +60,8 @@ blink_core_sources("animation") { ...@@ -60,6 +60,8 @@ blink_core_sources("animation") {
"css/css_animations.h", "css/css_animations.h",
"css/css_keyframe_effect_model.cc", "css/css_keyframe_effect_model.cc",
"css/css_keyframe_effect_model.h", "css/css_keyframe_effect_model.h",
"css/css_scroll_timeline.cc",
"css/css_scroll_timeline.h",
"css/css_timing_data.cc", "css/css_timing_data.cc",
"css/css_timing_data.h", "css/css_timing_data.h",
"css/css_transition.cc", "css/css_transition.cc",
......
...@@ -42,6 +42,7 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable { ...@@ -42,6 +42,7 @@ class CORE_EXPORT AnimationTimeline : public ScriptWrappable {
virtual bool IsDocumentTimeline() const { return false; } virtual bool IsDocumentTimeline() const { return false; }
virtual bool IsScrollTimeline() const { return false; } virtual bool IsScrollTimeline() const { return false; }
virtual bool IsCSSScrollTimeline() const { return false; }
virtual bool IsActive() const = 0; virtual bool IsActive() const = 0;
virtual double ZeroTimeInSeconds() = 0; virtual double ZeroTimeInSeconds() = 0;
// https://drafts.csswg.org/web-animations/#monotonically-increasing-timeline // https://drafts.csswg.org/web-animations/#monotonically-increasing-timeline
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.h" #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.h"
#include "third_party/blink/renderer/core/animation/css/css_animation.h" #include "third_party/blink/renderer/core/animation/css/css_animation.h"
#include "third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.h" #include "third_party/blink/renderer/core/animation/css/css_keyframe_effect_model.h"
#include "third_party/blink/renderer/core/animation/css/css_scroll_timeline.h"
#include "third_party/blink/renderer/core/animation/css/css_transition.h" #include "third_party/blink/renderer/core/animation/css/css_transition.h"
#include "third_party/blink/renderer/core/animation/css_interpolation_types_map.h" #include "third_party/blink/renderer/core/animation/css_interpolation_types_map.h"
#include "third_party/blink/renderer/core/animation/document_animations.h" #include "third_party/blink/renderer/core/animation/document_animations.h"
...@@ -51,13 +52,10 @@ ...@@ -51,13 +52,10 @@
#include "third_party/blink/renderer/core/animation/interpolation_type.h" #include "third_party/blink/renderer/core/animation/interpolation_type.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h" #include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h" #include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline_offset.h" #include "third_party/blink/renderer/core/animation/scroll_timeline_offset.h"
#include "third_party/blink/renderer/core/animation/timing_calculations.h" #include "third_party/blink/renderer/core/animation/timing_calculations.h"
#include "third_party/blink/renderer/core/animation/transition_interpolation.h" #include "third_party/blink/renderer/core/animation/transition_interpolation.h"
#include "third_party/blink/renderer/core/animation/worklet_animation_base.h" #include "third_party/blink/renderer/core/animation/worklet_animation_base.h"
#include "third_party/blink/renderer/core/css/css_id_selector_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_keyframe_rule.h" #include "third_party/blink/renderer/core/css/css_keyframe_rule.h"
#include "third_party/blink/renderer/core/css/css_property_equality.h" #include "third_party/blink/renderer/core/css/css_property_equality.h"
#include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/css_value_list.h"
...@@ -428,109 +426,15 @@ AnimationTimeDelta IterationElapsedTime(const AnimationEffect& effect, ...@@ -428,109 +426,15 @@ AnimationTimeDelta IterationElapsedTime(const AnimationEffect& effect,
return iteration_duration * (iteration_boundary - iteration_start); return iteration_duration * (iteration_boundary - iteration_start);
} }
bool IsIdentifier(const CSSValue* value, CSSValueID value_id) { CSSScrollTimeline* CreateCSSScrollTimeline(Element* element,
if (const auto* ident = DynamicTo<CSSIdentifierValue>(value)) StyleRuleScrollTimeline* rule) {
return ident->GetValueID() == value_id;
return false;
}
bool IsAuto(const CSSValue* value) {
return IsIdentifier(value, CSSValueID::kAuto);
}
bool IsNone(const CSSValue* value) {
return IsIdentifier(value, CSSValueID::kNone);
}
const cssvalue::CSSIdSelectorValue* GetIdSelectorValue(const CSSValue* value) {
if (const auto* selector = DynamicTo<CSSFunctionValue>(value)) {
if (selector->FunctionType() != CSSValueID::kSelector)
return nullptr;
DCHECK_EQ(selector->length(), 1u);
return DynamicTo<cssvalue::CSSIdSelectorValue>(selector->Item(0));
}
return nullptr;
}
Element* ComputeScrollSource(Element* element, const CSSValue* value) {
if (const auto* id = GetIdSelectorValue(value))
return element->GetDocument().getElementById(id->Id());
if (IsNone(value))
return nullptr;
DCHECK(!value || IsAuto(value));
return element->GetDocument().scrollingElement();
}
ScrollTimeline::ScrollDirection ComputeScrollDirection(const CSSValue* value) {
CSSValueID value_id = CSSValueID::kAuto;
if (const auto* identifier = DynamicTo<CSSIdentifierValue>(value))
value_id = identifier->GetValueID();
switch (value_id) {
case CSSValueID::kInline:
return ScrollTimeline::Inline;
case CSSValueID::kHorizontal:
return ScrollTimeline::Horizontal;
case CSSValueID::kVertical:
return ScrollTimeline::Vertical;
case CSSValueID::kAuto:
case CSSValueID::kBlock:
default:
return ScrollTimeline::Block;
}
}
ScrollTimelineOffset* ComputeScrollOffset(const CSSValue* value) {
if (auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value))
return MakeGarbageCollected<ScrollTimelineOffset>(primitive_value);
DCHECK(!value || IsAuto(value));
return MakeGarbageCollected<ScrollTimelineOffset>();
}
HeapVector<Member<ScrollTimelineOffset>>* ComputeScrollOffsets(
const CSSValue* start,
const CSSValue* end) {
auto* offsets =
MakeGarbageCollected<HeapVector<Member<ScrollTimelineOffset>>>();
offsets->push_back(ComputeScrollOffset(start));
offsets->push_back(ComputeScrollOffset(end));
return offsets;
}
base::Optional<double> ComputeTimeRange(const CSSValue* value) {
if (auto* primitive = DynamicTo<CSSPrimitiveValue>(value))
return primitive->ComputeSeconds() * 1000.0;
// TODO(crbug.com/1097041): Support 'auto' value.
return base::nullopt;
}
struct CSSScrollTimelineOptions {
STACK_ALLOCATED();
public:
CSSScrollTimelineOptions(Element* element, StyleRuleScrollTimeline& rule)
: source(ComputeScrollSource(element, rule.GetSource())),
direction(ComputeScrollDirection(rule.GetOrientation())),
offsets(ComputeScrollOffsets(rule.GetStart(), rule.GetEnd())),
time_range(ComputeTimeRange(rule.GetTimeRange())) {}
Element* source;
ScrollTimeline::ScrollDirection direction;
HeapVector<Member<ScrollTimelineOffset>>* offsets;
base::Optional<double> time_range;
};
ScrollTimeline* CreateScrollTimeline(Element* element,
StyleRuleScrollTimeline* rule) {
if (!rule) if (!rule)
return nullptr; return nullptr;
CSSScrollTimelineOptions options(element, *rule); CSSScrollTimeline::Options options(element, *rule);
if (!options.time_range) if (!options.IsValid())
return nullptr; return nullptr;
auto* scroll_timeline = MakeGarbageCollected<ScrollTimeline>( auto* scroll_timeline =
&element->GetDocument(), options.source, options.direction, MakeGarbageCollected<CSSScrollTimeline>(&element->GetDocument(), options);
options.offsets, *options.time_range);
// It's is not allowed for a style resolve to create timelines that // It's is not allowed for a style resolve to create timelines that
// needs timing updates (i.e. AnimationTimeline::NeedsAnimationTimingUpdate() // needs timing updates (i.e. AnimationTimeline::NeedsAnimationTimingUpdate()
// must return false). Servicing animations after creation preserves this // must return false). Servicing animations after creation preserves this
...@@ -550,7 +454,7 @@ AnimationTimeline* ComputeTimeline(Element* element, ...@@ -550,7 +454,7 @@ AnimationTimeline* ComputeTimeline(Element* element,
return nullptr; return nullptr;
} }
if (rule) { if (rule) {
if (auto* timeline = CreateScrollTimeline(element, rule)) if (auto* timeline = CreateCSSScrollTimeline(element, rule))
return timeline; return timeline;
} }
return nullptr; return nullptr;
......
// Copyright 2020 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/css/css_scroll_timeline.h"
#include "third_party/blink/renderer/core/css/css_id_selector_value.h"
#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/style_rule.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
namespace blink {
namespace {
bool IsIdentifier(const CSSValue* value, CSSValueID value_id) {
if (const auto* ident = DynamicTo<CSSIdentifierValue>(value))
return ident->GetValueID() == value_id;
return false;
}
bool IsAuto(const CSSValue* value) {
return IsIdentifier(value, CSSValueID::kAuto);
}
bool IsNone(const CSSValue* value) {
return IsIdentifier(value, CSSValueID::kNone);
}
const cssvalue::CSSIdSelectorValue* GetIdSelectorValue(const CSSValue* value) {
if (const auto* selector = DynamicTo<CSSFunctionValue>(value)) {
if (selector->FunctionType() != CSSValueID::kSelector)
return nullptr;
DCHECK_EQ(selector->length(), 1u);
return DynamicTo<cssvalue::CSSIdSelectorValue>(selector->Item(0));
}
return nullptr;
}
Element* ComputeScrollSource(Element* element, const CSSValue* value) {
if (const auto* id = GetIdSelectorValue(value))
return element->GetDocument().getElementById(id->Id());
if (IsNone(value))
return nullptr;
DCHECK(!value || IsAuto(value));
return element->GetDocument().scrollingElement();
}
ScrollTimeline::ScrollDirection ComputeScrollDirection(const CSSValue* value) {
CSSValueID value_id = CSSValueID::kAuto;
if (const auto* identifier = DynamicTo<CSSIdentifierValue>(value))
value_id = identifier->GetValueID();
switch (value_id) {
case CSSValueID::kInline:
return ScrollTimeline::Inline;
case CSSValueID::kHorizontal:
return ScrollTimeline::Horizontal;
case CSSValueID::kVertical:
return ScrollTimeline::Vertical;
case CSSValueID::kAuto:
case CSSValueID::kBlock:
default:
return ScrollTimeline::Block;
}
}
ScrollTimelineOffset* ComputeScrollOffset(const CSSValue* value) {
if (auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value))
return MakeGarbageCollected<ScrollTimelineOffset>(primitive_value);
DCHECK(!value || IsAuto(value));
return MakeGarbageCollected<ScrollTimelineOffset>();
}
HeapVector<Member<ScrollTimelineOffset>>* ComputeScrollOffsets(
const CSSValue* start,
const CSSValue* end) {
auto* offsets =
MakeGarbageCollected<HeapVector<Member<ScrollTimelineOffset>>>();
offsets->push_back(ComputeScrollOffset(start));
offsets->push_back(ComputeScrollOffset(end));
return offsets;
}
base::Optional<double> ComputeTimeRange(const CSSValue* value) {
if (auto* primitive = DynamicTo<CSSPrimitiveValue>(value))
return primitive->ComputeSeconds() * 1000.0;
// TODO(crbug.com/1097041): Support 'auto' value.
return base::nullopt;
}
} // anonymous namespace
CSSScrollTimeline::Options::Options(Element* element,
StyleRuleScrollTimeline& rule)
: source_(ComputeScrollSource(element, rule.GetSource())),
direction_(ComputeScrollDirection(rule.GetOrientation())),
offsets_(ComputeScrollOffsets(rule.GetStart(), rule.GetEnd())),
time_range_(ComputeTimeRange(rule.GetTimeRange())) {}
CSSScrollTimeline::CSSScrollTimeline(Document* document, const Options& options)
: ScrollTimeline(document,
options.source_,
options.direction_,
options.offsets_,
*options.time_range_) {
DCHECK(options.IsValid());
}
} // namespace blink
// Copyright 2020 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_CSS_CSS_SCROLL_TIMELINE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_SCROLL_TIMELINE_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
namespace blink {
class Document;
class Element;
class StyleRuleScrollTimeline;
// A CSSScrollTimeline is like a ScrollTimeline, except it originates from
// an @scroll-timeline rule.
class CORE_EXPORT CSSScrollTimeline : public ScrollTimeline {
public:
struct Options {
STACK_ALLOCATED();
public:
Options(Element*, StyleRuleScrollTimeline&);
// TODO(crbug.com/1097041): Support 'auto' value.
bool IsValid() const { return time_range_.has_value(); }
private:
friend class CSSScrollTimeline;
Element* source_;
ScrollTimeline::ScrollDirection direction_;
HeapVector<Member<ScrollTimelineOffset>>* offsets_;
base::Optional<double> time_range_;
};
CSSScrollTimeline(Document*, const Options&);
// AnimationTimeline implementation.
bool IsCSSScrollTimeline() const override { return true; }
};
template <>
struct DowncastTraits<CSSScrollTimeline> {
static bool AllowFrom(const AnimationTimeline& value) {
return value.IsCSSScrollTimeline();
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_SCROLL_TIMELINE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment