mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
layout_2020: Add support for transitions and animations
This commit is contained in:
parent
c183f95297
commit
a238597a18
7 changed files with 54 additions and 18 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2849,6 +2849,7 @@ dependencies = [
|
||||||
"embedder_traits",
|
"embedder_traits",
|
||||||
"euclid",
|
"euclid",
|
||||||
"fnv",
|
"fnv",
|
||||||
|
"fxhash",
|
||||||
"gfx",
|
"gfx",
|
||||||
"gfx_traits",
|
"gfx_traits",
|
||||||
"html5ever",
|
"html5ever",
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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| {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue