Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
style: Add a generic way to deal with lists of values, ditch all uses…
… of as_servo in style/animations.rs
  • Loading branch information
emilio committed Jul 1, 2016
1 parent 07da4e4 commit ba53c4e
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 53 deletions.
63 changes: 23 additions & 40 deletions components/style/animation.rs
Expand Up @@ -253,10 +253,10 @@ impl PropertyAnimation {
new_style: &mut C)
-> Vec<PropertyAnimation> {
let mut result = vec![];
let box_style = new_style.as_servo().get_box();
let transition_property = box_style.transition_property.0[transition_index];
let timing_function = *box_style.transition_timing_function.0.get_mod(transition_index);
let duration = *box_style.transition_duration.0.get_mod(transition_index);
let box_style = new_style.get_box();
let transition_property = box_style.transition_property_at(transition_index);
let timing_function = box_style.transition_timing_function_mod(transition_index);
let duration = box_style.transition_duration_mod(transition_index);


if transition_property != TransitionProperty::All {
Expand Down Expand Up @@ -333,23 +333,6 @@ impl PropertyAnimation {
}
}

/// Accesses an element of an array, "wrapping around" using modular arithmetic. This is needed
/// to handle [repeatable lists][lists] of differing lengths.
///
/// [lists]: https://drafts.csswg.org/css-transitions/#animtype-repeatable-list
pub trait GetMod {
type Item;
fn get_mod(&self, i: usize) -> &Self::Item;
}

impl<T> GetMod for Vec<T> {
type Item = T;
#[inline]
fn get_mod(&self, i: usize) -> &T {
&(*self)[i % self.len()]
}
}

/// Inserts transitions into the queue of running animations as applicable for
/// the given style difference. This is called from the layout worker threads.
/// Returns true if any animations were kicked off and false otherwise.
Expand All @@ -362,7 +345,7 @@ pub fn start_transitions_if_applicable<Impl: SelectorImplExt>(new_animations_sen
new_style: &mut Arc<Impl::ComputedValues>)
-> bool {
let mut had_animations = false;
for i in 0..new_style.get_box().transition_count() {
for i in 0..new_style.get_box().transition_property_count() {
// Create any property animations, if applicable.
let property_animations = PropertyAnimation::from_transition(i, old_style, Arc::make_mut(new_style));
for property_animation in property_animations {
Expand All @@ -372,14 +355,14 @@ pub fn start_transitions_if_applicable<Impl: SelectorImplExt>(new_animations_sen
property_animation.update(Arc::get_mut(new_style).unwrap(), 0.0);

// Kick off the animation.
let box_style = new_style.get_box();
let now = time::precise_time_s();
let box_style = new_style.as_servo().get_box();
let start_time =
now + (box_style.transition_delay.0.get_mod(i).seconds() as f64);
now + (box_style.transition_delay_mod(i).seconds() as f64);
new_animations_sender
.lock().unwrap()
.send(Animation::Transition(node, start_time, AnimationFrame {
duration: box_style.transition_duration.0.get_mod(i).seconds() as f64,
duration: box_style.transition_duration_mod(i).seconds() as f64,
property_animation: property_animation,
}, /* is_expired = */ false)).unwrap();

Expand Down Expand Up @@ -427,10 +410,10 @@ pub fn maybe_start_animations<Impl: SelectorImplExt>(context: &SharedStyleContex
return false;
}

let box_style = new_style.as_servo().get_box();
for (i, name) in box_style.animation_name.0.iter().enumerate() {
let box_style = new_style.get_box();
for (i, name) in box_style.animation_name_iter().enumerate() {
debug!("maybe_start_animations: name={}", name);
let total_duration = box_style.animation_duration.0.get_mod(i).seconds();
let total_duration = box_style.animation_duration_mod(i).seconds();
if total_duration == 0. {
continue
}
Expand All @@ -446,16 +429,16 @@ pub fn maybe_start_animations<Impl: SelectorImplExt>(context: &SharedStyleContex
continue;
}

let delay = box_style.animation_delay.0.get_mod(i).seconds();
let delay = box_style.animation_delay_mod(i).seconds();
let now = time::precise_time_s();
let animation_start = now + delay as f64;
let duration = box_style.animation_duration.0.get_mod(i).seconds();
let iteration_state = match *box_style.animation_iteration_count.0.get_mod(i) {
let duration = box_style.animation_duration_mod(i).seconds();
let iteration_state = match box_style.animation_iteration_count_mod(i) {
AnimationIterationCount::Infinite => KeyframesIterationState::Infinite,
AnimationIterationCount::Number(n) => KeyframesIterationState::Finite(0, n),
};

let animation_direction = *box_style.animation_direction.0.get_mod(i);
let animation_direction = box_style.animation_direction_mod(i);

let initial_direction = match animation_direction {
AnimationDirection::normal |
Expand All @@ -464,7 +447,7 @@ pub fn maybe_start_animations<Impl: SelectorImplExt>(context: &SharedStyleContex
AnimationDirection::alternate_reverse => AnimationDirection::reverse,
};

let running_state = match *box_style.animation_play_state.0.get_mod(i) {
let running_state = match box_style.animation_play_state_mod(i) {
AnimationPlayState::paused => KeyframesRunningState::Paused(0.),
AnimationPlayState::running => KeyframesRunningState::Running,
};
Expand Down Expand Up @@ -556,9 +539,9 @@ where Impl: SelectorImplExt,

debug_assert!(!animation.steps.is_empty());

let maybe_index = style.as_servo()
.get_box().animation_name.0.iter()
.position(|animation_name| name == animation_name);
let maybe_index = style.get_box()
.animation_name_iter()
.position(|animation_name| *name == animation_name);

let index = match maybe_index {
Some(index) => index,
Expand All @@ -568,7 +551,7 @@ where Impl: SelectorImplExt,
}
};

let total_duration = style.as_servo().get_box().animation_duration.0.get_mod(index).seconds() as f64;
let total_duration = style.get_box().animation_duration_mod(index).seconds() as f64;
if total_duration == 0. {
debug!("update_style_for_animation: zero duration for animation {:?}", name);
return;
Expand Down Expand Up @@ -648,9 +631,9 @@ where Impl: SelectorImplExt,

// NB: The spec says that the timing function can be overwritten
// from the keyframe style.
let mut timing_function = *style.as_servo().get_box().animation_timing_function.0.get_mod(index);
if !from_style.as_servo().get_box().animation_timing_function.0.is_empty() {
timing_function = from_style.as_servo().get_box().animation_timing_function.0[0];
let mut timing_function = style.get_box().animation_timing_function_mod(index);
if from_style.get_box().animation_timing_function_count() != 0 {
timing_function = from_style.get_box().animation_timing_function_at(0);
}

let target_style = compute_style_for_animation_step(context,
Expand Down
3 changes: 2 additions & 1 deletion components/style/properties/data.py
Expand Up @@ -47,7 +47,7 @@ def gecko_constant(self, value):
class Longhand(object):
def __init__(self, style_struct, name, animatable=None, derived_from=None, keyword=None,
predefined_type=None, custom_cascade=False, experimental=False, internal=False,
need_clone=False, gecko_ffi_name=None):
need_clone=False, need_index=False, gecko_ffi_name=None):
self.name = name
self.keyword = keyword
self.predefined_type = predefined_type
Expand All @@ -58,6 +58,7 @@ def __init__(self, style_struct, name, animatable=None, derived_from=None, keywo
self.custom_cascade = custom_cascade
self.internal = internal
self.need_clone = need_clone
self.need_index = need_index
self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
self.derived_from = (derived_from or "").split()

Expand Down
2 changes: 2 additions & 0 deletions components/style/properties/helpers.mako.rs
Expand Up @@ -225,6 +225,8 @@
}
}

pub use self::${to_camel_case(name)} as SingleComputedValue;

define_css_keyword_enum! { ${to_camel_case(name)}:
% for value in data.longhands_by_name[name].keyword.values_for(product):
"${value}" => ${to_rust_ident(value)},
Expand Down
34 changes: 27 additions & 7 deletions components/style/properties/longhand/box.mako.rs
Expand Up @@ -7,8 +7,7 @@

<% data.new_style_struct("Box",
inherited=False,
gecko_name="Display",
additional_methods=[Method("transition_count", "usize")]) %>
gecko_name="Display") %>

// TODO(SimonSapin): don't parse `inline-table`, since we don't support it
<%helpers:longhand name="display"
Expand Down Expand Up @@ -285,7 +284,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
</%helpers:longhand>

// TODO(pcwalton): Multiple transitions.
<%helpers:longhand name="transition-duration" animatable="False">
<%helpers:longhand name="transition-duration"
need_index="True"
animatable="False">
use values::computed::ComputedValueAsSpecified;
use values::specified::Time;

Expand Down Expand Up @@ -343,7 +344,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",

// TODO(pcwalton): Lots more timing functions.
// TODO(pcwalton): Multiple transitions.
<%helpers:longhand name="transition-timing-function" animatable="False">
<%helpers:longhand name="transition-timing-function"
need_index="True"
animatable="False">
use self::computed_value::{StartEnd, TransitionTimingFunction};

use euclid::point::Point2D;
Expand Down Expand Up @@ -541,7 +544,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
}
</%helpers:longhand>

<%helpers:longhand name="transition-property" animatable="False">
<%helpers:longhand name="transition-property"
need_index="True"
animatable="False">
pub use self::computed_value::SingleComputedValue as SingleSpecifiedValue;
pub use self::computed_value::T as SpecifiedValue;

Expand Down Expand Up @@ -592,14 +597,17 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
}
</%helpers:longhand>

<%helpers:longhand name="transition-delay" animatable="False">
<%helpers:longhand name="transition-delay"
need_index="True"
animatable="False">
pub use properties::longhands::transition_duration::{SingleSpecifiedValue, SpecifiedValue};
pub use properties::longhands::transition_duration::{computed_value};
pub use properties::longhands::transition_duration::{get_initial_single_value};
pub use properties::longhands::transition_duration::{get_initial_value, parse, parse_one};
</%helpers:longhand>

<%helpers:longhand name="animation-name"
need_index="True"
animatable="False">
use values::computed::ComputedValueAsSpecified;

Expand All @@ -608,6 +616,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
use std::fmt;
use string_cache::Atom;

pub use string_cache::Atom as SingleComputedValue;

#[derive(Debug, Clone, PartialEq, HeapSizeOf)]
pub struct T(pub Vec<Atom>);

Expand Down Expand Up @@ -647,26 +657,32 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
</%helpers:longhand>

<%helpers:longhand name="animation-duration"
need_index="True"
animatable="False">
pub use super::transition_duration::computed_value;
pub use super::transition_duration::{parse, get_initial_value};
pub use super::transition_duration::SpecifiedValue;
</%helpers:longhand>

<%helpers:longhand name="animation-timing-function"
need_index="True"
animatable="False">
pub use super::transition_timing_function::computed_value;
pub use super::transition_timing_function::{parse, get_initial_value};
pub use super::transition_timing_function::SpecifiedValue;
</%helpers:longhand>

<%helpers:longhand name="animation-iteration-count" animatable="False">
<%helpers:longhand name="animation-iteration-count"
need_index="True"
animatable="False">
use values::computed::ComputedValueAsSpecified;

pub mod computed_value {
use cssparser::ToCss;
use std::fmt;

pub use self::AnimationIterationCount as SingleComputedValue;

#[derive(Debug, Clone, PartialEq, HeapSizeOf)]
pub enum AnimationIterationCount {
Number(u32),
Expand Down Expand Up @@ -731,18 +747,22 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",

${helpers.keyword_list("animation-direction",
"normal reverse alternate alternate-reverse",
need_index=True,
animatable=False)}

${helpers.keyword_list("animation-play-state",
"running paused",
need_clone=True,
need_index=True,
animatable=False)}

${helpers.keyword_list("animation-fill-mode",
"none forwards backwards both",
need_index=True,
animatable=False)}

<%helpers:longhand name="animation-delay"
need_index="True"
animatable="False">
pub use super::transition_duration::computed_value;
pub use super::transition_duration::{parse, get_initial_value};
Expand Down
65 changes: 60 additions & 5 deletions components/style/properties/properties.mako.rs
Expand Up @@ -1082,12 +1082,61 @@ pub mod style_struct_traits {
#[allow(non_snake_case)]
fn clone_${longhand.ident}(&self) -> longhands::${longhand.ident}::computed_value::T;
% endif
% if longhand.need_index:
#[allow(non_snake_case)]
fn ${longhand.ident}_count(&self) -> usize;

#[allow(non_snake_case)]
fn ${longhand.ident}_at(&self, index: usize)
-> longhands::${longhand.ident}::computed_value::SingleComputedValue;

#[allow(non_snake_case)]
#[inline]
fn ${longhand.ident}_iter<'a>(&'a self)
-> ${longhand.camel_case}Iter<'a, Self> {
${longhand.camel_case}Iter {
style_struct: self,
current: 0,
max: self.${longhand.ident}_count(),
}
}

#[allow(non_snake_case)]
#[inline]
fn ${longhand.ident}_mod(&self, index: usize)
-> longhands::${longhand.ident}::computed_value::SingleComputedValue {
self.${longhand.ident}_at(index % self.${longhand.ident}_count())
}
% endif
% endfor
% for additional in style_struct.additional_methods:
#[allow(non_snake_case)]
${additional.declare()}
% endfor
}

% for longhand in style_struct.longhands:
% if longhand.need_index:
pub struct ${longhand.camel_case}Iter<'a, S: ${style_struct.trait_name} + 'static> {
style_struct: &'a S,
current: usize,
max: usize,
}

impl<'a, S: ${style_struct.trait_name} + 'static> Iterator for ${longhand.camel_case}Iter<'a, S> {
type Item = longhands::${longhand.ident}::computed_value::SingleComputedValue;

fn next(&mut self) -> Option<Self::Item> {
self.current += 1;
if self.current <= self.max {
Some(self.style_struct.${longhand.ident}_at(self.current - 1))
} else {
None
}
}
}
% endif
% endfor
% endfor
}

Expand Down Expand Up @@ -1140,18 +1189,24 @@ pub mod style_structs {
self.${longhand.ident}.clone()
}
% endif

% if longhand.need_index:
fn ${longhand.ident}_count(&self) -> usize {
self.${longhand.ident}.0.len()
}

fn ${longhand.ident}_at(&self, index: usize)
-> longhands::${longhand.ident}::computed_value::SingleComputedValue {
self.${longhand.ident}.0[index].clone()
}
% endif
% endfor
% if style_struct.trait_name == "Border":
% for side in ["top", "right", "bottom", "left"]:
fn border_${side}_has_nonzero_width(&self) -> bool {
self.border_${side}_width != ::app_units::Au(0)
}
% endfor
% elif style_struct.trait_name == "Box":
#[inline]
fn transition_count(&self) -> usize {
self.transition_property.0.len()
}
% elif style_struct.trait_name == "Font":
fn compute_font_hash(&mut self) {
// Corresponds to the fields in `gfx::font_template::FontTemplateDescriptor`.
Expand Down

0 comments on commit ba53c4e

Please sign in to comment.