diff options
Diffstat (limited to 'components/layout/animation.rs')
-rw-r--r-- | components/layout/animation.rs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/components/layout/animation.rs b/components/layout/animation.rs new file mode 100644 index 00000000000..571228afccb --- /dev/null +++ b/components/layout/animation.rs @@ -0,0 +1,104 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! CSS transitions and animations. + +use flow::{self, Flow}; +use incremental::{self, RestyleDamage}; + +use clock_ticks; +use gfx::display_list::OpaqueNode; +use layout_task::{LayoutTask, LayoutTaskData}; +use msg::constellation_msg::{Msg, PipelineId}; +use script::layout_interface::Animation; +use std::mem; +use std::sync::mpsc::Sender; +use style::animation::{GetMod, PropertyAnimation}; +use style::properties::ComputedValues; + +/// Inserts transitions into the queue of running animations as applicable for the given style +/// difference. This is called from the layout worker threads. +pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>, + node: OpaqueNode, + old_style: &ComputedValues, + new_style: &mut ComputedValues) { + for i in range(0, new_style.get_animation().transition_property.0.len()) { + // Create any property animations, if applicable. + let property_animations = PropertyAnimation::from_transition(i, old_style, new_style); + for property_animation in property_animations.into_iter() { + // Set the property to the initial value. + property_animation.update(new_style, 0.0); + + // Kick off the animation. + let now = clock_ticks::precise_time_s(); + let animation_style = new_style.get_animation(); + let start_time = now + animation_style.transition_delay.0.get_mod(i).seconds(); + new_animations_sender.send(Animation { + node: node.id(), + property_animation: property_animation, + start_time: start_time, + end_time: start_time + + animation_style.transition_duration.0.get_mod(i).seconds(), + }).unwrap() + } + } +} + +/// Processes any new animations that were discovered after style recalculation. +pub fn process_new_animations(rw_data: &mut LayoutTaskData, pipeline_id: PipelineId) { + while let Ok(animation) = rw_data.new_animations_receiver.try_recv() { + rw_data.running_animations.push(animation) + } + + let animations_are_running = !rw_data.running_animations.is_empty(); + rw_data.constellation_chan + .0 + .send(Msg::ChangeRunningAnimationsState(pipeline_id, animations_are_running)) + .unwrap(); +} + +/// Recalculates style for an animation. This does *not* run with the DOM lock held. +pub fn recalc_style_for_animation(flow: &mut Flow, animation: &Animation) { + let mut damage = RestyleDamage::empty(); + flow.mutate_fragments(&mut |fragment| { + if fragment.node.id() != animation.node { + return + } + + let now = clock_ticks::precise_time_s(); + let mut progress = (now - animation.start_time) / animation.duration(); + if progress > 1.0 { + progress = 1.0 + } + if progress <= 0.0 { + return + } + + let mut new_style = fragment.style.clone(); + animation.property_animation.update(&mut *new_style.make_unique(), progress); + damage.insert(incremental::compute_damage(&Some(fragment.style.clone()), &new_style)); + fragment.style = new_style + }); + + let base = flow::mut_base(flow); + base.restyle_damage.insert(damage); + for kid in base.children.iter_mut() { + recalc_style_for_animation(kid, animation) + } +} + +/// Handles animation updates. +pub fn tick_all_animations(layout_task: &LayoutTask, rw_data: &mut LayoutTaskData) { + let running_animations = mem::replace(&mut rw_data.running_animations, Vec::new()); + let now = clock_ticks::precise_time_s(); + for running_animation in running_animations.into_iter() { + layout_task.tick_animation(running_animation, rw_data); + + if now < running_animation.end_time { + // Keep running the animation if it hasn't expired. + rw_data.running_animations.push(running_animation) + } + } +} + |