Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

layout_2020: Add animations and transitions support #26486

Merged
merged 2 commits into from May 19, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

layout_2020: Add support for transitions and animations

  • Loading branch information
mrobinson committed May 19, 2020
commit a238597a18033086a699a5c0d624a88cedd62d4e

Some generated files are not rendered by default. Learn more.

@@ -20,6 +20,7 @@ cssparser = "0.27"
embedder_traits = { path = "../embedder_traits" }
euclid = "0.20"
fnv = "1.0"
fxhash = "0.2"
gfx = { path = "../gfx" }
gfx_traits = { path = "../gfx_traits" }
html5ever = "0.25"
@@ -26,6 +26,7 @@ use crate::style_ext::{Display, DisplayGeneratingBox};
use crate::DefiniteContainingBlock;
use app_units::Au;
use euclid::default::{Point2D, Rect, Size2D};
use fxhash::FxHashSet;
use gfx_traits::print_tree::PrintTree;
use script_layout_interface::wrapper_traits::LayoutNode;
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> {
let mut bounding_box = PhysicalRect::zero();
self.find(|fragment, containing_block| {
@@ -27,7 +27,7 @@ use crossbeam_channel::{Receiver, Sender};
use embedder_traits::resources::{self, Resource};
use euclid::{default::Size2D as UntypedSize2D, Point2D, Rect, Scale, Size2D};
use fnv::FnvHashMap;
use fxhash::FxHashMap;
use fxhash::{FxHashMap, FxHashSet};
use gfx::font_cache_thread::FontCacheThread;
use gfx::font_context;
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::thread;
use std::time::Duration;
use style::animation::ElementAnimationSet;
use style::context::{
QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext,
};
use style::dom::OpaqueNode;
use style::dom::{TDocument, TElement, TNode};
use style::driver;
use style::error_reporting::RustLogReporter;
@@ -572,6 +574,7 @@ impl LayoutThread {
snapshot_map: &'a SnapshotMap,
origin: ImmutableOrigin,
animation_timeline_value: f64,
animation_states: ServoArc<RwLock<FxHashMap<OpaqueNode, ElementAnimationSet>>>,
) -> LayoutContext<'a> {
LayoutContext {
id: self.id,
@@ -581,7 +584,7 @@ impl LayoutThread {
options: GLOBAL_STYLE_DATA.options.clone(),
guards,
visited_styles_enabled: false,
animation_states: Default::default(),
animation_states,
registered_speculative_painters: &self.registered_painters,
current_time_for_animations: animation_timeline_value,
traversal_flags: TraversalFlags::empty(),
@@ -1062,8 +1065,13 @@ impl LayoutThread {
self.stylist.flush(&guards, Some(element), Some(&map));

// Create a layout context for use throughout the following passes.
let mut layout_context =
self.build_layout_context(guards.clone(), &map, origin, data.animation_timeline_value);
let mut layout_context = self.build_layout_context(
guards.clone(),
&map,
origin,
data.animation_timeline_value,
data.animations.clone(),
);

let traversal = RecalcStyle::new(layout_context);
let token = {
@@ -1273,6 +1281,11 @@ impl LayoutThread {
document: Option<&ServoLayoutDocument>,
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 let Some(box_tree) = &*self.box_tree.borrow() {
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 {
@@ -161,7 +161,6 @@ ${helpers.predefined_type(
"Time",
"computed::Time::zero()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Time::zero()",
parse_method="parse_non_negative",
vector=True,
@@ -176,7 +175,6 @@ ${helpers.predefined_type(
"TimingFunction",
"computed::TimingFunction::ease()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::TimingFunction::ease()",
vector=True,
need_index=True,
@@ -190,7 +188,6 @@ ${helpers.predefined_type(
"TransitionProperty",
"computed::TransitionProperty::all()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::TransitionProperty::all()",
vector=True,
allow_empty="NotInitial",
@@ -205,7 +202,6 @@ ${helpers.predefined_type(
"Time",
"computed::Time::zero()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Time::zero()",
vector=True,
need_index=True,
@@ -221,7 +217,6 @@ ${helpers.predefined_type(
"AnimationName",
"computed::AnimationName::none()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::AnimationName::none()",
vector=True,
need_index=True,
@@ -236,7 +231,6 @@ ${helpers.predefined_type(
"Time",
"computed::Time::zero()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Time::zero()",
parse_method="parse_non_negative",
vector=True,
@@ -253,7 +247,6 @@ ${helpers.predefined_type(
"TimingFunction",
"computed::TimingFunction::ease()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::TimingFunction::ease()",
vector=True,
need_index=True,
@@ -268,7 +261,6 @@ ${helpers.predefined_type(
"AnimationIterationCount",
"computed::AnimationIterationCount::one()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::AnimationIterationCount::one()",
vector=True,
need_index=True,
@@ -283,7 +275,6 @@ ${helpers.single_keyword(
"animation-direction",
"normal reverse alternate alternate-reverse",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
need_index=True,
animation_value_type="none",
vector=True,
@@ -299,7 +290,6 @@ ${helpers.single_keyword(
"animation-play-state",
"running paused",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
need_index=True,
animation_value_type="none",
vector=True,
@@ -328,7 +318,6 @@ ${helpers.predefined_type(
"Time",
"computed::Time::zero()",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Time::zero()",
vector=True,
need_index=True,
@@ -28,7 +28,6 @@ ${helpers.two_properties_shorthand(
"(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 {
($context: expr, $input: expr, $var: ident, $prop_module: ident) => {
if $var.is_none() {
@@ -43,7 +42,7 @@ macro_rules! try_parse_one {
}

<%helpers:shorthand name="transition"
engines="gecko servo-2013"
engines="gecko servo-2013 servo-2020"
extra_prefixes="moz:layout.css.prefixes.transitions webkit"
sub_properties="transition-property transition-duration
transition-timing-function
@@ -189,7 +188,7 @@ macro_rules! try_parse_one {
</%helpers:shorthand>

<%helpers:shorthand name="animation"
engines="gecko servo-2013"
engines="gecko servo-2013 servo-2020"
extra_prefixes="moz:layout.css.prefixes.animations webkit"
sub_properties="animation-name animation-duration
animation-timing-function animation-delay
@@ -9,6 +9,8 @@ skip: true
skip: true
[CSS2]
skip: false
[css-animations]
skip: false
[css-backgrounds]
skip: false
[css-content]
@@ -23,6 +25,8 @@ skip: true
skip: false
[css-transforms]
skip: false
[css-transitions]
skip: false
[css-ui]
skip: false
[filter-effects]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.