layout_2020: Add support for transitions and animations

This commit is contained in:
Martin Robinson 2020-05-11 10:20:40 +02:00
parent c183f95297
commit a238597a18
7 changed files with 54 additions and 18 deletions

1
Cargo.lock generated
View file

@ -2849,6 +2849,7 @@ dependencies = [
"embedder_traits", "embedder_traits",
"euclid", "euclid",
"fnv", "fnv",
"fxhash",
"gfx", "gfx",
"gfx_traits", "gfx_traits",
"html5ever", "html5ever",

View file

@ -20,6 +20,7 @@ cssparser = "0.27"
embedder_traits = { path = "../embedder_traits" } embedder_traits = { path = "../embedder_traits" }
euclid = "0.20" euclid = "0.20"
fnv = "1.0" fnv = "1.0"
fxhash = "0.2"
gfx = { path = "../gfx" } gfx = { path = "../gfx" }
gfx_traits = { path = "../gfx_traits" } gfx_traits = { path = "../gfx_traits" }
html5ever = "0.25" html5ever = "0.25"

View file

@ -26,6 +26,7 @@ use crate::style_ext::{Display, DisplayGeneratingBox};
use crate::DefiniteContainingBlock; use crate::DefiniteContainingBlock;
use app_units::Au; use app_units::Au;
use euclid::default::{Point2D, Rect, Size2D}; use euclid::default::{Point2D, Rect, Size2D};
use fxhash::FxHashSet;
use gfx_traits::print_tree::PrintTree; use gfx_traits::print_tree::PrintTree;
use script_layout_interface::wrapper_traits::LayoutNode; use script_layout_interface::wrapper_traits::LayoutNode;
use script_layout_interface::{LayoutElementType, LayoutNodeType}; use script_layout_interface::{LayoutElementType, LayoutNodeType};
@ -303,6 +304,15 @@ impl FragmentTree {
}) })
} }
pub fn remove_nodes_in_fragment_tree_from_set(&self, set: &mut FxHashSet<OpaqueNode>) {
self.find(|fragment, _| {
if let Some(tag) = fragment.tag().as_ref() {
set.remove(tag);
}
None::<()>
});
}
pub fn get_content_box_for_node(&self, requested_node: OpaqueNode) -> Rect<Au> { pub fn get_content_box_for_node(&self, requested_node: OpaqueNode) -> Rect<Au> {
let mut bounding_box = PhysicalRect::zero(); let mut bounding_box = PhysicalRect::zero();
self.find(|fragment, containing_block| { self.find(|fragment, containing_block| {

View file

@ -27,7 +27,7 @@ use crossbeam_channel::{Receiver, Sender};
use embedder_traits::resources::{self, Resource}; use embedder_traits::resources::{self, Resource};
use euclid::{default::Size2D as UntypedSize2D, Point2D, Rect, Scale, Size2D}; use euclid::{default::Size2D as UntypedSize2D, Point2D, Rect, Scale, Size2D};
use fnv::FnvHashMap; use fnv::FnvHashMap;
use fxhash::FxHashMap; use fxhash::{FxHashMap, FxHashSet};
use gfx::font_cache_thread::FontCacheThread; use gfx::font_cache_thread::FontCacheThread;
use gfx::font_context; use gfx::font_context;
use gfx_traits::{node_id_from_scroll_id, Epoch}; use gfx_traits::{node_id_from_scroll_id, Epoch};
@ -80,9 +80,11 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use style::animation::ElementAnimationSet;
use style::context::{ use style::context::{
QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext, QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext,
}; };
use style::dom::OpaqueNode;
use style::dom::{TDocument, TElement, TNode}; use style::dom::{TDocument, TElement, TNode};
use style::driver; use style::driver;
use style::error_reporting::RustLogReporter; use style::error_reporting::RustLogReporter;
@ -572,6 +574,7 @@ impl LayoutThread {
snapshot_map: &'a SnapshotMap, snapshot_map: &'a SnapshotMap,
origin: ImmutableOrigin, origin: ImmutableOrigin,
animation_timeline_value: f64, animation_timeline_value: f64,
animation_states: ServoArc<RwLock<FxHashMap<OpaqueNode, ElementAnimationSet>>>,
) -> LayoutContext<'a> { ) -> LayoutContext<'a> {
LayoutContext { LayoutContext {
id: self.id, id: self.id,
@ -581,7 +584,7 @@ impl LayoutThread {
options: GLOBAL_STYLE_DATA.options.clone(), options: GLOBAL_STYLE_DATA.options.clone(),
guards, guards,
visited_styles_enabled: false, visited_styles_enabled: false,
animation_states: Default::default(), animation_states,
registered_speculative_painters: &self.registered_painters, registered_speculative_painters: &self.registered_painters,
current_time_for_animations: animation_timeline_value, current_time_for_animations: animation_timeline_value,
traversal_flags: TraversalFlags::empty(), traversal_flags: TraversalFlags::empty(),
@ -1062,8 +1065,13 @@ impl LayoutThread {
self.stylist.flush(&guards, Some(element), Some(&map)); self.stylist.flush(&guards, Some(element), Some(&map));
// Create a layout context for use throughout the following passes. // Create a layout context for use throughout the following passes.
let mut layout_context = let mut layout_context = self.build_layout_context(
self.build_layout_context(guards.clone(), &map, origin, data.animation_timeline_value); guards.clone(),
&map,
origin,
data.animation_timeline_value,
data.animations.clone(),
);
let traversal = RecalcStyle::new(layout_context); let traversal = RecalcStyle::new(layout_context);
let token = { let token = {
@ -1273,6 +1281,11 @@ impl LayoutThread {
document: Option<&ServoLayoutDocument>, document: Option<&ServoLayoutDocument>,
context: &mut LayoutContext, context: &mut LayoutContext,
) { ) {
Self::cancel_animations_for_nodes_not_in_fragment_tree(
&mut *(context.style_context.animation_states.write()),
&fragment_tree,
);
if self.trace_layout { if self.trace_layout {
if let Some(box_tree) = &*self.box_tree.borrow() { if let Some(box_tree) = &*self.box_tree.borrow() {
layout_debug::begin_trace(box_tree.clone(), fragment_tree.clone()); layout_debug::begin_trace(box_tree.clone(), fragment_tree.clone());
@ -1356,6 +1369,25 @@ impl LayoutThread {
}, },
}) })
} }
/// Cancel animations for any nodes which have been removed from fragment tree.
/// TODO(mrobinson): We should look into a way of doing this during flow tree construction.
/// This also doesn't yet handles nodes that have been reparented.
fn cancel_animations_for_nodes_not_in_fragment_tree(
animation_states: &mut FxHashMap<OpaqueNode, ElementAnimationSet>,
root: &FragmentTree,
) {
// Assume all nodes have been removed until proven otherwise.
let mut invalid_nodes: FxHashSet<OpaqueNode> = animation_states.keys().cloned().collect();
root.remove_nodes_in_fragment_tree_from_set(&mut invalid_nodes);
// Cancel animations for any nodes that are no longer in the fragment tree.
for node in &invalid_nodes {
if let Some(state) = animation_states.get_mut(node) {
state.cancel_all_animations();
}
}
}
} }
impl ProfilerMetadataFactory for LayoutThread { impl ProfilerMetadataFactory for LayoutThread {

View file

@ -161,7 +161,6 @@ ${helpers.predefined_type(
"Time", "Time",
"computed::Time::zero()", "computed::Time::zero()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Time::zero()", initial_specified_value="specified::Time::zero()",
parse_method="parse_non_negative", parse_method="parse_non_negative",
vector=True, vector=True,
@ -176,7 +175,6 @@ ${helpers.predefined_type(
"TimingFunction", "TimingFunction",
"computed::TimingFunction::ease()", "computed::TimingFunction::ease()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::TimingFunction::ease()", initial_specified_value="specified::TimingFunction::ease()",
vector=True, vector=True,
need_index=True, need_index=True,
@ -190,7 +188,6 @@ ${helpers.predefined_type(
"TransitionProperty", "TransitionProperty",
"computed::TransitionProperty::all()", "computed::TransitionProperty::all()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::TransitionProperty::all()", initial_specified_value="specified::TransitionProperty::all()",
vector=True, vector=True,
allow_empty="NotInitial", allow_empty="NotInitial",
@ -205,7 +202,6 @@ ${helpers.predefined_type(
"Time", "Time",
"computed::Time::zero()", "computed::Time::zero()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Time::zero()", initial_specified_value="specified::Time::zero()",
vector=True, vector=True,
need_index=True, need_index=True,
@ -221,7 +217,6 @@ ${helpers.predefined_type(
"AnimationName", "AnimationName",
"computed::AnimationName::none()", "computed::AnimationName::none()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::AnimationName::none()", initial_specified_value="specified::AnimationName::none()",
vector=True, vector=True,
need_index=True, need_index=True,
@ -236,7 +231,6 @@ ${helpers.predefined_type(
"Time", "Time",
"computed::Time::zero()", "computed::Time::zero()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Time::zero()", initial_specified_value="specified::Time::zero()",
parse_method="parse_non_negative", parse_method="parse_non_negative",
vector=True, vector=True,
@ -253,7 +247,6 @@ ${helpers.predefined_type(
"TimingFunction", "TimingFunction",
"computed::TimingFunction::ease()", "computed::TimingFunction::ease()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::TimingFunction::ease()", initial_specified_value="specified::TimingFunction::ease()",
vector=True, vector=True,
need_index=True, need_index=True,
@ -268,7 +261,6 @@ ${helpers.predefined_type(
"AnimationIterationCount", "AnimationIterationCount",
"computed::AnimationIterationCount::one()", "computed::AnimationIterationCount::one()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::AnimationIterationCount::one()", initial_specified_value="specified::AnimationIterationCount::one()",
vector=True, vector=True,
need_index=True, need_index=True,
@ -283,7 +275,6 @@ ${helpers.single_keyword(
"animation-direction", "animation-direction",
"normal reverse alternate alternate-reverse", "normal reverse alternate alternate-reverse",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
need_index=True, need_index=True,
animation_value_type="none", animation_value_type="none",
vector=True, vector=True,
@ -299,7 +290,6 @@ ${helpers.single_keyword(
"animation-play-state", "animation-play-state",
"running paused", "running paused",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
need_index=True, need_index=True,
animation_value_type="none", animation_value_type="none",
vector=True, vector=True,
@ -328,7 +318,6 @@ ${helpers.predefined_type(
"Time", "Time",
"computed::Time::zero()", "computed::Time::zero()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Time::zero()", initial_specified_value="specified::Time::zero()",
vector=True, vector=True,
need_index=True, need_index=True,

View file

@ -28,7 +28,6 @@ ${helpers.two_properties_shorthand(
"(https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-clip-box)", "(https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-clip-box)",
)} )}
#[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
macro_rules! try_parse_one { macro_rules! try_parse_one {
($context: expr, $input: expr, $var: ident, $prop_module: ident) => { ($context: expr, $input: expr, $var: ident, $prop_module: ident) => {
if $var.is_none() { if $var.is_none() {
@ -43,7 +42,7 @@ macro_rules! try_parse_one {
} }
<%helpers:shorthand name="transition" <%helpers:shorthand name="transition"
engines="gecko servo-2013" engines="gecko servo-2013 servo-2020"
extra_prefixes="moz:layout.css.prefixes.transitions webkit" extra_prefixes="moz:layout.css.prefixes.transitions webkit"
sub_properties="transition-property transition-duration sub_properties="transition-property transition-duration
transition-timing-function transition-timing-function
@ -189,7 +188,7 @@ macro_rules! try_parse_one {
</%helpers:shorthand> </%helpers:shorthand>
<%helpers:shorthand name="animation" <%helpers:shorthand name="animation"
engines="gecko servo-2013" engines="gecko servo-2013 servo-2020"
extra_prefixes="moz:layout.css.prefixes.animations webkit" extra_prefixes="moz:layout.css.prefixes.animations webkit"
sub_properties="animation-name animation-duration sub_properties="animation-name animation-duration
animation-timing-function animation-delay animation-timing-function animation-delay

View file

@ -9,6 +9,8 @@ skip: true
skip: true skip: true
[CSS2] [CSS2]
skip: false skip: false
[css-animations]
skip: false
[css-backgrounds] [css-backgrounds]
skip: false skip: false
[css-content] [css-content]
@ -23,6 +25,8 @@ skip: true
skip: false skip: false
[css-transforms] [css-transforms]
skip: false skip: false
[css-transitions]
skip: false
[css-ui] [css-ui]
skip: false skip: false
[filter-effects] [filter-effects]