diff --git a/components/layout/animation.rs b/components/layout/animation.rs index 571228afccb..258ac7d0a39 100644 --- a/components/layout/animation.rs +++ b/components/layout/animation.rs @@ -93,7 +93,7 @@ pub fn tick_all_animations(layout_task: &LayoutTask, rw_data: &mut LayoutTaskDat 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); + layout_task.tick_animation(&running_animation, rw_data); if now < running_animation.end_time { // Keep running the animation if it hasn't expired. diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index c31fbb0bab9..054b8f51dc9 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -923,7 +923,7 @@ impl LayoutTask { animation::tick_all_animations(self, &mut rw_data) } - pub fn tick_animation<'a>(&'a self, animation: Animation, rw_data: &mut LayoutTaskData) { + pub fn tick_animation<'a>(&'a self, animation: &Animation, rw_data: &mut LayoutTaskData) { let reflow_info = Reflow { goal: ReflowGoal::ForDisplay, page_clip_rect: MAX_RECT, diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index d04acc36c67..4859c075058 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -178,7 +178,7 @@ impl ScriptLayoutChan for OpaqueScriptLayoutChannel { pub type OpaqueNode = uintptr_t; /// State relating to an animation. -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct Animation { /// An opaque reference to the DOM node participating in the animation. pub node: OpaqueNode, diff --git a/components/style/animation.rs b/components/style/animation.rs index f1237c34650..06e073bf745 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -6,14 +6,29 @@ use properties::ComputedValues; use properties::longhands::transition_property::computed_value::TransitionProperty; use properties::longhands::transition_timing_function::computed_value::{StartEnd}; use properties::longhands::transition_timing_function::computed_value::{TransitionTimingFunction}; +use properties::longhands::z_index::computed_value::T as ZIndex; +use properties::longhands::visibility::computed_value::T as Visibility; +use properties::longhands::vertical_align::computed_value::T as VerticalAlign; +use properties::longhands::border_spacing::computed_value::T as BorderSpacing; +use properties::longhands::line_height::computed_value::T as LineHeight; +use properties::longhands::font_weight::computed_value::T as FontWeight; +use properties::longhands::clip::computed_value::ClipRect; +use properties::longhands::text_shadow::computed_value::TextShadow; +use properties::longhands::text_shadow::computed_value::T as TextShadowList; +use properties::longhands::background_position::computed_value::T as BackgroundPosition; use properties::longhands::transition_property; -use values::computed::{LengthOrPercentageOrAuto, Time}; +use values::computed::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, LengthOrPercentage, Length, Time}; +use values::CSSFloat; +use cssparser::{RGBA, Color}; use std::num::Float; +use std::cmp::Ordering; +use std::iter::repeat; +use std::num::FromPrimitive; use util::bezier::Bezier; use util::geometry::Au; -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct PropertyAnimation { property: AnimatedProperty, timing_function: TransitionTimingFunction, @@ -62,28 +77,70 @@ impl PropertyAnimation { new_style: &mut ComputedValues) -> Option { let animation_style = new_style.get_animation(); - let animated_property = match transition_property { - TransitionProperty::All => { - panic!("Don't use `TransitionProperty::All` with \ - `PropertyAnimation::from_transition_property`!") - } - TransitionProperty::Top => { - AnimatedProperty::Top(old_style.get_positionoffsets().top, - new_style.get_positionoffsets().top) - } - TransitionProperty::Right => { - AnimatedProperty::Right(old_style.get_positionoffsets().right, - new_style.get_positionoffsets().right) - } - TransitionProperty::Bottom => { - AnimatedProperty::Bottom(old_style.get_positionoffsets().bottom, - new_style.get_positionoffsets().bottom) - } - TransitionProperty::Left => { - AnimatedProperty::Left(old_style.get_positionoffsets().left, - new_style.get_positionoffsets().left) - } - }; + macro_rules! match_transition { + ( $( [$name:ident; $structname:ident; $field:ident] ),* ) => { + match transition_property { + TransitionProperty::All => { + panic!("Don't use `TransitionProperty::All` with \ + `PropertyAnimation::from_transition_property`!") + } + $( + TransitionProperty::$name => { + AnimatedProperty::$name(old_style.$structname().$field, + new_style.$structname().$field) + } + )* + TransitionProperty::TextShadow => { + AnimatedProperty::TextShadow(old_style.get_effects().text_shadow.clone(), + new_style.get_effects().text_shadow.clone()) + } + } + } + } + let animated_property = match_transition!( + [BackgroundColor; get_background; background_color], + [BackgroundPosition; get_background; background_position], + [BorderBottomColor; get_border; border_bottom_color], + [BorderBottomWidth; get_border; border_bottom_width], + [BorderLeftColor; get_border; border_left_color], + [BorderLeftWidth; get_border; border_left_width], + [BorderRightColor; get_border; border_right_color], + [BorderRightWidth; get_border; border_right_width], + [BorderSpacing; get_inheritedtable; border_spacing], + [BorderTopColor; get_border; border_top_color], + [BorderTopWidth; get_border; border_top_width], + [Bottom; get_positionoffsets; bottom], + [Color; get_color; color], + [Clip; get_effects; clip], + [FontSize; get_font; font_size], + [FontWeight; get_font; font_weight], + [Height; get_box; height], + [Left; get_positionoffsets; bottom], + [LetterSpacing; get_inheritedtext; letter_spacing], + [LineHeight; get_inheritedbox; line_height], + [MarginBottom; get_margin; margin_bottom], + [MarginLeft; get_margin; margin_left], + [MarginRight; get_margin; margin_right], + [MarginTop; get_margin; margin_top], + [MaxHeight; get_box; max_height], + [MaxWidth; get_box; max_width], + [MinHeight; get_box; min_height], + [MinWidth; get_box; min_width], + [Opacity; get_effects; opacity], + [OutlineColor; get_outline; outline_color], + [OutlineWidth; get_outline; outline_width], + [PaddingBottom; get_margin; margin_bottom], + [PaddingLeft; get_margin; margin_left], + [PaddingRight; get_margin; margin_right], + [PaddingTop; get_margin; margin_top], + [Right; get_positionoffsets; right], + [TextIndent; get_inheritedtext; text_indent], + [Top; get_positionoffsets; top], + [VerticalAlign; get_box; vertical_align], + [Visibility; get_inheritedbox; visibility], + [Width; get_box; width], + [WordSpacing; get_inheritedtext; word_spacing], + [ZIndex; get_box; z_index]); let property_animation = PropertyAnimation { property: animated_property, @@ -112,28 +169,64 @@ impl PropertyAnimation { (time * (steps as f64)).floor() / (steps as f64) } }; - match self.property { - AnimatedProperty::Top(ref start, ref end) => { - if let Some(value) = start.interpolate(end, progress) { - style.mutate_positionoffsets().top = value + + macro_rules! match_property( + ( $( [$name:ident; $structname:ident; $field:ident] ),* ) => { + match self.property { + $( + AnimatedProperty::$name(ref start, ref end) => { + if let Some(value) = start.interpolate(end, progress) { + style.$structname().$field = value + } + } + )* } - } - AnimatedProperty::Right(ref start, ref end) => { - if let Some(value) = start.interpolate(end, progress) { - style.mutate_positionoffsets().right = value - } - } - AnimatedProperty::Bottom(ref start, ref end) => { - if let Some(value) = start.interpolate(end, progress) { - style.mutate_positionoffsets().bottom = value - } - } - AnimatedProperty::Left(ref start, ref end) => { - if let Some(value) = start.interpolate(end, progress) { - style.mutate_positionoffsets().left = value - } - } - } + }); + match_property!( + [BackgroundColor; mutate_background; background_color], + [BackgroundPosition; mutate_background; background_position], + [BorderBottomColor; mutate_border; border_bottom_color], + [BorderBottomWidth; mutate_border; border_bottom_width], + [BorderLeftColor; mutate_border; border_left_color], + [BorderLeftWidth; mutate_border; border_left_width], + [BorderRightColor; mutate_border; border_right_color], + [BorderRightWidth; mutate_border; border_right_width], + [BorderSpacing; mutate_inheritedtable; border_spacing], + [BorderTopColor; mutate_border; border_top_color], + [BorderTopWidth; mutate_border; border_top_width], + [Bottom; mutate_positionoffsets; bottom], + [Color; mutate_color; color], + [Clip; mutate_effects; clip], + [FontSize; mutate_font; font_size], + [FontWeight; mutate_font; font_weight], + [Height; mutate_box; height], + [Left; mutate_positionoffsets; bottom], + [LetterSpacing; mutate_inheritedtext; letter_spacing], + [LineHeight; mutate_inheritedbox; line_height], + [MarginBottom; mutate_margin; margin_bottom], + [MarginLeft; mutate_margin; margin_left], + [MarginRight; mutate_margin; margin_right], + [MarginTop; mutate_margin; margin_top], + [MaxHeight; mutate_box; max_height], + [MaxWidth; mutate_box; max_width], + [MinHeight; mutate_box; min_height], + [MinWidth; mutate_box; min_width], + [Opacity; mutate_effects; opacity], + [OutlineColor; mutate_outline; outline_color], + [OutlineWidth; mutate_outline; outline_width], + [PaddingBottom; mutate_margin; margin_bottom], + [PaddingLeft; mutate_margin; margin_left], + [PaddingRight; mutate_margin; margin_right], + [PaddingTop; mutate_margin; margin_top], + [Right; mutate_positionoffsets; right], + [TextIndent; mutate_inheritedtext; text_indent], + [TextShadow; mutate_effects; text_shadow], + [Top; mutate_positionoffsets; top], + [VerticalAlign; mutate_box; vertical_align], + [Visibility; mutate_inheritedbox; visibility], + [Width; mutate_box; width], + [WordSpacing; mutate_inheritedtext; word_spacing], + [ZIndex; mutate_box; z_index]); } #[inline] @@ -142,12 +235,52 @@ impl PropertyAnimation { } } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] enum AnimatedProperty { - Top(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), - Right(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + BackgroundColor(Color, Color), + BackgroundPosition(BackgroundPosition, BackgroundPosition), + BorderBottomColor(Color, Color), + BorderBottomWidth(Length, Length), + BorderLeftColor(Color, Color), + BorderLeftWidth(Length, Length), + BorderRightColor(Color, Color), + BorderRightWidth(Length, Length), + BorderSpacing(BorderSpacing, BorderSpacing), + BorderTopColor(Color, Color), + BorderTopWidth(Length, Length), Bottom(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + Color(RGBA, RGBA), + Clip(Option, Option), + FontSize(Length, Length), + FontWeight(FontWeight, FontWeight), + Height(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), Left(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + LetterSpacing(Option, Option), + LineHeight(LineHeight, LineHeight), + MarginBottom(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + MarginLeft(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + MarginRight(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + MarginTop(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + MaxHeight(LengthOrPercentageOrNone, LengthOrPercentageOrNone), + MaxWidth(LengthOrPercentageOrNone, LengthOrPercentageOrNone), + MinHeight(LengthOrPercentage, LengthOrPercentage), + MinWidth(LengthOrPercentage, LengthOrPercentage), + Opacity(CSSFloat, CSSFloat), + OutlineColor(Color, Color), + OutlineWidth(Length, Length), + PaddingBottom(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + PaddingLeft(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + PaddingRight(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + PaddingTop(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + Right(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + TextIndent(LengthOrPercentage, LengthOrPercentage), + TextShadow(TextShadowList, TextShadowList), + Top(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + VerticalAlign(VerticalAlign, VerticalAlign), + Visibility(Visibility, Visibility), + Width(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + WordSpacing(Option, Option), + ZIndex(ZIndex, ZIndex), } impl AnimatedProperty { @@ -157,7 +290,47 @@ impl AnimatedProperty { AnimatedProperty::Top(ref a, ref b) | AnimatedProperty::Right(ref a, ref b) | AnimatedProperty::Bottom(ref a, ref b) | - AnimatedProperty::Left(ref a, ref b) => a == b, + AnimatedProperty::Left(ref a, ref b) | + AnimatedProperty::MarginTop(ref a, ref b) | + AnimatedProperty::MarginRight(ref a, ref b) | + AnimatedProperty::MarginBottom(ref a, ref b) | + AnimatedProperty::MarginLeft(ref a, ref b) | + AnimatedProperty::PaddingTop(ref a, ref b) | + AnimatedProperty::PaddingRight(ref a, ref b) | + AnimatedProperty::PaddingBottom(ref a, ref b) | + AnimatedProperty::PaddingLeft(ref a, ref b) | + AnimatedProperty::Width(ref a, ref b) | + AnimatedProperty::Height(ref a, ref b) => a == b, + AnimatedProperty::MaxWidth(ref a, ref b) | + AnimatedProperty::MaxHeight(ref a, ref b) => a == b, + AnimatedProperty::MinWidth(ref a, ref b) | + AnimatedProperty::MinHeight(ref a, ref b) | + AnimatedProperty::TextIndent(ref a, ref b) => a == b, + AnimatedProperty::FontSize(ref a, ref b) | + AnimatedProperty::BorderTopWidth(ref a, ref b) | + AnimatedProperty::BorderRightWidth(ref a, ref b) | + AnimatedProperty::BorderBottomWidth(ref a, ref b) | + AnimatedProperty::BorderLeftWidth(ref a, ref b) => a == b, + AnimatedProperty::BorderTopColor(ref a, ref b) | + AnimatedProperty::BorderRightColor(ref a, ref b) | + AnimatedProperty::BorderBottomColor(ref a, ref b) | + AnimatedProperty::BorderLeftColor(ref a, ref b) | + AnimatedProperty::OutlineColor(ref a, ref b) | + AnimatedProperty::BackgroundColor(ref a, ref b) => a == b, + AnimatedProperty::LineHeight(ref a, ref b) => a == b, + AnimatedProperty::LetterSpacing(ref a, ref b) => a == b, + AnimatedProperty::BackgroundPosition(ref a, ref b) => a == b, + AnimatedProperty::BorderSpacing(ref a, ref b) => a == b, + AnimatedProperty::Clip(ref a, ref b) => a == b, + AnimatedProperty::Color(ref a, ref b) => a == b, + AnimatedProperty::FontWeight(ref a, ref b) => a == b, + AnimatedProperty::Opacity(ref a, ref b) => a == b, + AnimatedProperty::OutlineWidth(ref a, ref b) => a == b, + AnimatedProperty::TextShadow(ref a, ref b) => a == b, + AnimatedProperty::VerticalAlign(ref a, ref b) => a == b, + AnimatedProperty::Visibility(ref a, ref b) => a == b, + AnimatedProperty::WordSpacing(ref a, ref b) => a == b, + AnimatedProperty::ZIndex(ref a, ref b) => a == b, } } } @@ -173,6 +346,20 @@ impl Interpolate for Au { } } +impl Interpolate for Option where T:Interpolate { + #[inline] + fn interpolate(&self, other: &Option, time: f64) -> Option> { + match (self, other) { + (&Some(ref this), &Some(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(Some(value)) + }) + } + (_, _) => None + } + } +} + impl Interpolate for f64 { #[inline] fn interpolate(&self, other: &f64, time: f64) -> Option { @@ -180,6 +367,136 @@ impl Interpolate for f64 { } } +impl Interpolate for f32 { + #[inline] + fn interpolate(&self, other: &f32, time: f64) -> Option { + Some(*self + (*other - *self) * (time as f32)) + } +} + +impl Interpolate for i32 { + #[inline] + fn interpolate(&self, other: &i32, time: f64) -> Option { + let a = *self as f64; + let b = *other as f64; + Some((a + (b - a) * time).round() as i32) + } +} + +impl Interpolate for Visibility { + #[inline] + fn interpolate(&self, other: &Visibility, time: f64) + -> Option { + match (*self, *other) { + (Visibility::visible, _) | (_, Visibility::visible) => { + if time >= 0.0 && time <= 1.0 { + Some(Visibility::visible) + } else if time < 0.0 { + Some(*self) + } else { + Some(*other) + } + } + (_, _) => None, + } + } +} + +impl Interpolate for ZIndex { + #[inline] + fn interpolate(&self, other: &ZIndex, time: f64) + -> Option { + match (*self, *other) { + (ZIndex::Number(ref this), + ZIndex::Number(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(ZIndex::Number(value)) + }) + } + (_, _) => None, + } + } +} + +impl Interpolate for VerticalAlign { + #[inline] + fn interpolate(&self, other: &VerticalAlign, time: f64) + -> Option { + match (*self, *other) { + (VerticalAlign::Length(ref this), + VerticalAlign::Length(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(VerticalAlign::Length(value)) + }) + } + (_, _) => None, + } + } +} + +impl Interpolate for BorderSpacing { + #[inline] + fn interpolate(&self, other: &BorderSpacing, time: f64) + -> Option { + self.horizontal.interpolate(&other.horizontal, time).and_then(|horizontal| { + self.vertical.interpolate(&other.vertical, time).and_then(|vertical| { + Some(BorderSpacing { horizontal: horizontal, vertical: vertical }) + }) + }) + } +} + +impl Interpolate for RGBA { + #[inline] + fn interpolate(&self, other: &RGBA, time: f64) -> Option { + match (self.red.interpolate(&other.red, time), + self.green.interpolate(&other.green, time), + self.blue.interpolate(&other.blue, time), + self.alpha.interpolate(&other.alpha, time)) { + (Some(red), Some(green), Some(blue), Some(alpha)) => { + Some(RGBA { red: red, green: green, blue: blue, alpha: alpha }) + } + (_, _, _, _) => None + } + } +} + +impl Interpolate for Color { + #[inline] + fn interpolate(&self, other: &Color, time: f64) -> Option { + match (*self, *other) { + (Color::RGBA(ref this), Color::RGBA(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(Color::RGBA(value)) + }) + } + (_, _) => None, + } + } +} + +impl Interpolate for LengthOrPercentage { + #[inline] + fn interpolate(&self, other: &LengthOrPercentage, time: f64) + -> Option { + match (*self, *other) { + (LengthOrPercentage::Length(ref this), + LengthOrPercentage::Length(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LengthOrPercentage::Length(value)) + }) + } + (LengthOrPercentage::Percentage(ref this), + LengthOrPercentage::Percentage(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LengthOrPercentage::Percentage(value)) + }) + } + (_, _) => None, + } + } +} + impl Interpolate for LengthOrPercentageOrAuto { #[inline] fn interpolate(&self, other: &LengthOrPercentageOrAuto, time: f64) @@ -205,6 +522,137 @@ impl Interpolate for LengthOrPercentageOrAuto { } } +impl Interpolate for LengthOrPercentageOrNone { + #[inline] + fn interpolate(&self, other: &LengthOrPercentageOrNone, time: f64) + -> Option { + match (*self, *other) { + (LengthOrPercentageOrNone::Length(ref this), + LengthOrPercentageOrNone::Length(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LengthOrPercentageOrNone::Length(value)) + }) + } + (LengthOrPercentageOrNone::Percentage(ref this), + LengthOrPercentageOrNone::Percentage(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LengthOrPercentageOrNone::Percentage(value)) + }) + } + (LengthOrPercentageOrNone::None, LengthOrPercentageOrNone::None) => { + Some(LengthOrPercentageOrNone::None) + } + (_, _) => None, + } + } +} + +impl Interpolate for LineHeight { + #[inline] + fn interpolate(&self, other: &LineHeight, time: f64) + -> Option { + match (*self, *other) { + (LineHeight::Length(ref this), + LineHeight::Length(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LineHeight::Length(value)) + }) + } + (LineHeight::Number(ref this), + LineHeight::Number(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LineHeight::Number(value)) + }) + } + (LineHeight::Normal, LineHeight::Normal) => { + Some(LineHeight::Normal) + } + (_, _) => None, + } + } +} + +impl Interpolate for FontWeight { + #[inline] + fn interpolate(&self, other: &FontWeight, time: f64) + -> Option { + let a = (*self as isize) as f64; + let b = (*other as isize) as f64; + let weight: Option = FromPrimitive::from_isize((a + (b - a) * time).round() as isize); + weight + } +} + +impl Interpolate for ClipRect { + #[inline] + fn interpolate(&self, other: &ClipRect, time: f64) + -> Option { + match (self.top.interpolate(&other.top, time), + self.right.interpolate(&other.right, time), + self.bottom.interpolate(&other.bottom, time), + self.left.interpolate(&other.left, time)) { + (Some(top), Some(right), Some(bottom), Some(left)) => { + Some(ClipRect { top: top, right: right, bottom: bottom, left: left }) + }, + (_, _, _, _) => None, + } + } +} + +impl Interpolate for BackgroundPosition { + #[inline] + fn interpolate(&self, other: &BackgroundPosition, time: f64) + -> Option { + match (self.horizontal.interpolate(&other.horizontal, time), + self.vertical.interpolate(&other.vertical, time)) { + (Some(horizontal), Some(vertical)) => { + Some(BackgroundPosition { horizontal: horizontal, vertical: vertical }) + }, + (_, _) => None, + } + } +} + +impl Interpolate for TextShadow { + #[inline] + fn interpolate(&self, other: &TextShadow, time: f64) + -> Option { + match (self.offset_x.interpolate(&other.offset_x, time), + self.offset_y.interpolate(&other.offset_y, time), + self.blur_radius.interpolate(&other.blur_radius, time), + self.color.interpolate(&other.color, time)) { + (Some(offset_x), Some(offset_y), Some(blur_radius), Some(color)) => { + Some(TextShadow { offset_x: offset_x, offset_y: offset_y, blur_radius: blur_radius, color: color }) + }, + (_, _, _, _) => None, + } + } +} + +impl Interpolate for TextShadowList { + #[inline] + fn interpolate(&self, other: &TextShadowList, time: f64) + -> Option { + let zero = TextShadow { + offset_x: Au(0), + offset_y: Au(0), + blur_radius: Au(0), + color: Color::RGBA(RGBA { + red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0 + }) + }; + + let interpolate_each = |(a, b): (&TextShadow, &TextShadow)| { + a.interpolate(b, time).unwrap() + }; + + Some(TextShadowList(match self.0.len().cmp(&other.0.len()) { + Ordering::Less => other.0.iter().chain(repeat(&zero)).zip(other.0.iter()).map(interpolate_each).collect(), + _ => self.0.iter().zip(other.0.iter().chain(repeat(&zero))).map(interpolate_each).collect(), + })) + } +} + /// Accesses an element of an array, "wrapping around" using modular arithmetic. This is needed /// to handle values of differing lengths according to CSS-TRANSITIONS ยง 2. pub trait GetMod { diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index f6bf227ace8..51234eece8b 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -385,7 +385,7 @@ pub mod longhands { use cssparser::ToCss; use text_writer::{self, TextWriter}; - #[derive(PartialEq, Clone, Eq, Copy)] + #[derive(PartialEq, Clone, Eq, Copy, Debug)] pub enum T { Auto, Number(i32), @@ -1195,7 +1195,7 @@ pub mod longhands { pub mod computed_value { use values::computed::LengthOrPercentage; - #[derive(PartialEq, Copy, Clone)] + #[derive(PartialEq, Copy, Clone, Debug)] pub struct T { pub horizontal: LengthOrPercentage, pub vertical: LengthOrPercentage, @@ -1597,7 +1597,7 @@ pub mod longhands { } pub mod computed_value { use std::fmt; - #[derive(PartialEq, Eq, Copy, Clone, Hash)] + #[derive(PartialEq, Eq, Copy, Clone, Hash, FromPrimitive)] pub enum T { % for weight in range(100, 901, 100): Weight${weight} = ${weight}, @@ -3705,27 +3705,147 @@ pub mod longhands { #[derive(Copy, Clone, Debug, PartialEq)] pub enum TransitionProperty { All, - Top, - Right, + BackgroundColor, + BackgroundPosition, + BorderBottomColor, + BorderBottomWidth, + BorderLeftColor, + BorderLeftWidth, + BorderRightColor, + BorderRightWidth, + BorderSpacing, + BorderTopColor, + BorderTopWidth, Bottom, + Color, + Clip, + FontSize, + FontWeight, + Height, Left, + LetterSpacing, + LineHeight, + MarginBottom, + MarginLeft, + MarginRight, + MarginTop, + MaxHeight, + MaxWidth, + MinHeight, + MinWidth, + Opacity, + OutlineColor, + OutlineWidth, + PaddingBottom, + PaddingLeft, + PaddingRight, + PaddingTop, + Right, + TextIndent, + TextShadow, + Top, + VerticalAlign, + Visibility, + Width, + WordSpacing, + ZIndex, } - pub static ALL_TRANSITION_PROPERTIES: [TransitionProperty; 4] = [ - TransitionProperty::Top, - TransitionProperty::Right, + pub static ALL_TRANSITION_PROPERTIES: [TransitionProperty; 44] = [ + TransitionProperty::BackgroundColor, + TransitionProperty::BackgroundPosition, + TransitionProperty::BorderBottomColor, + TransitionProperty::BorderBottomWidth, + TransitionProperty::BorderLeftColor, + TransitionProperty::BorderLeftWidth, + TransitionProperty::BorderRightColor, + TransitionProperty::BorderRightWidth, + TransitionProperty::BorderSpacing, + TransitionProperty::BorderTopColor, + TransitionProperty::BorderTopWidth, TransitionProperty::Bottom, + TransitionProperty::Color, + TransitionProperty::Clip, + TransitionProperty::FontSize, + TransitionProperty::FontWeight, + TransitionProperty::Height, TransitionProperty::Left, + TransitionProperty::LetterSpacing, + TransitionProperty::LineHeight, + TransitionProperty::MarginBottom, + TransitionProperty::MarginLeft, + TransitionProperty::MarginRight, + TransitionProperty::MarginTop, + TransitionProperty::MaxHeight, + TransitionProperty::MaxWidth, + TransitionProperty::MinHeight, + TransitionProperty::MinWidth, + TransitionProperty::Opacity, + TransitionProperty::OutlineColor, + TransitionProperty::OutlineWidth, + TransitionProperty::PaddingBottom, + TransitionProperty::PaddingLeft, + TransitionProperty::PaddingRight, + TransitionProperty::PaddingTop, + TransitionProperty::Right, + TransitionProperty::TextIndent, + TransitionProperty::TextShadow, + TransitionProperty::Top, + TransitionProperty::VerticalAlign, + TransitionProperty::Visibility, + TransitionProperty::Width, + TransitionProperty::WordSpacing, + TransitionProperty::ZIndex, ]; impl ToCss for TransitionProperty { fn to_css(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { match *self { TransitionProperty::All => dest.write_str("all"), - TransitionProperty::Top => dest.write_str("top"), - TransitionProperty::Right => dest.write_str("right"), + TransitionProperty::BackgroundColor => dest.write_str("background-color"), + TransitionProperty::BackgroundPosition => dest.write_str("background-position"), + TransitionProperty::BorderBottomColor => dest.write_str("border-bottom-color"), + TransitionProperty::BorderBottomWidth => dest.write_str("border-bottom-width"), + TransitionProperty::BorderLeftColor => dest.write_str("border-left-color"), + TransitionProperty::BorderLeftWidth => dest.write_str("border-left-width"), + TransitionProperty::BorderRightColor => dest.write_str("border-right-color"), + TransitionProperty::BorderRightWidth => dest.write_str("border-right-width"), + TransitionProperty::BorderSpacing => dest.write_str("border-spacing"), + TransitionProperty::BorderTopColor => dest.write_str("border-top-color"), + TransitionProperty::BorderTopWidth => dest.write_str("border-top-width"), TransitionProperty::Bottom => dest.write_str("bottom"), + TransitionProperty::Color => dest.write_str("color"), + TransitionProperty::Clip => dest.write_str("clip"), + TransitionProperty::FontSize => dest.write_str("font-size"), + TransitionProperty::FontWeight => dest.write_str("font-weight"), + TransitionProperty::Height => dest.write_str("height"), TransitionProperty::Left => dest.write_str("left"), + TransitionProperty::LetterSpacing => dest.write_str("letter-spacing"), + TransitionProperty::LineHeight => dest.write_str("line-height"), + TransitionProperty::MarginBottom => dest.write_str("margin-bottom"), + TransitionProperty::MarginLeft => dest.write_str("margin-left"), + TransitionProperty::MarginRight => dest.write_str("margin-right"), + TransitionProperty::MarginTop => dest.write_str("margin-top"), + TransitionProperty::MaxHeight => dest.write_str("max-height"), + TransitionProperty::MaxWidth => dest.write_str("max-width"), + TransitionProperty::MinHeight => dest.write_str("min-height"), + TransitionProperty::MinWidth => dest.write_str("min-width"), + TransitionProperty::Opacity => dest.write_str("opacity"), + TransitionProperty::OutlineColor => dest.write_str("outline-color"), + TransitionProperty::OutlineWidth => dest.write_str("outline-width"), + TransitionProperty::PaddingBottom => dest.write_str("padding-bottom"), + TransitionProperty::PaddingLeft => dest.write_str("padding-left"), + TransitionProperty::PaddingRight => dest.write_str("padding-right"), + TransitionProperty::PaddingTop => dest.write_str("padding-top"), + TransitionProperty::Right => dest.write_str("right"), + TransitionProperty::TextIndent => dest.write_str("text-indent"), + TransitionProperty::TextShadow => dest.write_str("text-shadow"), + TransitionProperty::Top => dest.write_str("top"), + TransitionProperty::VerticalAlign => dest.write_str("vertical-align"), + TransitionProperty::Visibility => dest.write_str("visibility"), + TransitionProperty::Width => dest.write_str("width"), + TransitionProperty::WordSpacing => dest.write_str("word-spacing"), + TransitionProperty::ZIndex => dest.write_str("z-index"), } } } @@ -3758,10 +3878,50 @@ pub mod longhands { match_ignore_ascii_case! { try!(input.expect_ident()), "all" => Ok(TransitionProperty::All), - "top" => Ok(TransitionProperty::Top), - "right" => Ok(TransitionProperty::Right), + "background-color" => Ok(TransitionProperty::BackgroundColor), + "background-position" => Ok(TransitionProperty::BackgroundPosition), + "border-bottom-color" => Ok(TransitionProperty::BorderBottomColor), + "border-bottom-width" => Ok(TransitionProperty::BorderBottomWidth), + "border-left-color" => Ok(TransitionProperty::BorderLeftColor), + "border-left-width" => Ok(TransitionProperty::BorderLeftWidth), + "border-right-color" => Ok(TransitionProperty::BorderRightColor), + "border-right-width" => Ok(TransitionProperty::BorderRightWidth), + "border-spacing" => Ok(TransitionProperty::BorderSpacing), + "border-top-color" => Ok(TransitionProperty::BorderTopColor), + "border-top-width" => Ok(TransitionProperty::BorderTopWidth), "bottom" => Ok(TransitionProperty::Bottom), - "left" => Ok(TransitionProperty::Left) + "color" => Ok(TransitionProperty::Color), + "clip" => Ok(TransitionProperty::Clip), + "font-size" => Ok(TransitionProperty::FontSize), + "font-weight" => Ok(TransitionProperty::FontWeight), + "height" => Ok(TransitionProperty::Height), + "left" => Ok(TransitionProperty::Left), + "letter-spacing" => Ok(TransitionProperty::LetterSpacing), + "line-height" => Ok(TransitionProperty::LineHeight), + "margin-bottom" => Ok(TransitionProperty::MarginBottom), + "margin-left" => Ok(TransitionProperty::MarginLeft), + "margin-right" => Ok(TransitionProperty::MarginRight), + "margin-top" => Ok(TransitionProperty::MarginTop), + "max-height" => Ok(TransitionProperty::MaxHeight), + "max-width" => Ok(TransitionProperty::MaxWidth), + "min-height" => Ok(TransitionProperty::MinHeight), + "min-width" => Ok(TransitionProperty::MinWidth), + "opacity" => Ok(TransitionProperty::Opacity), + "outline-color" => Ok(TransitionProperty::OutlineColor), + "outline-width" => Ok(TransitionProperty::OutlineWidth), + "padding-bottom" => Ok(TransitionProperty::PaddingBottom), + "padding-left" => Ok(TransitionProperty::PaddingLeft), + "padding-right" => Ok(TransitionProperty::PaddingRight), + "padding-top" => Ok(TransitionProperty::PaddingTop), + "right" => Ok(TransitionProperty::Right), + "text-indent" => Ok(TransitionProperty::TextIndent), + "text-shadow" => Ok(TransitionProperty::TextShadow), + "top" => Ok(TransitionProperty::Top), + "vertical-align" => Ok(TransitionProperty::VerticalAlign), + "visibility" => Ok(TransitionProperty::Visibility), + "width" => Ok(TransitionProperty::Width), + "word-spacing" => Ok(TransitionProperty::WordSpacing), + "z-index" => Ok(TransitionProperty::ZIndex) _ => Err(()) } }