Animate many more CSS properties

This commit is contained in:
Joseph Seaton 2015-04-15 21:30:18 +01:00
parent 045831748e
commit d843526cb8
5 changed files with 673 additions and 65 deletions

View file

@ -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.

View file

@ -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,

View file

@ -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,

View file

@ -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<PropertyAnimation> {
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<ClipRect>, Option<ClipRect>),
FontSize(Length, Length),
FontWeight(FontWeight, FontWeight),
Height(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto),
Left(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto),
LetterSpacing(Option<Au>, Option<Au>),
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<Au>, Option<Au>),
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 <T> Interpolate for Option<T> where T:Interpolate {
#[inline]
fn interpolate(&self, other: &Option<T>, time: f64) -> Option<Option<T>> {
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<f64> {
@ -180,6 +367,136 @@ impl Interpolate for f64 {
}
}
impl Interpolate for f32 {
#[inline]
fn interpolate(&self, other: &f32, time: f64) -> Option<f32> {
Some(*self + (*other - *self) * (time as f32))
}
}
impl Interpolate for i32 {
#[inline]
fn interpolate(&self, other: &i32, time: f64) -> Option<i32> {
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<Visibility> {
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<ZIndex> {
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<VerticalAlign> {
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<BorderSpacing> {
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<RGBA> {
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<Color> {
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<LengthOrPercentage> {
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<LengthOrPercentageOrNone> {
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<LineHeight> {
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<FontWeight> {
let a = (*self as isize) as f64;
let b = (*other as isize) as f64;
let weight: Option<FontWeight> = FromPrimitive::from_isize((a + (b - a) * time).round() as isize);
weight
}
}
impl Interpolate for ClipRect {
#[inline]
fn interpolate(&self, other: &ClipRect, time: f64)
-> Option<ClipRect> {
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<BackgroundPosition> {
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<TextShadow> {
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<TextShadowList> {
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 {

View file

@ -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},
@ -3663,27 +3663,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<W>(&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"),
}
}
}
@ -3716,10 +3836,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(())
}
}