diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index b39a9816f07..c0d766dc544 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -2896,8 +2896,10 @@ impl Fragment { Matrix4D::create_skew(Radians::new(theta_x.radians()), Radians::new(theta_y.radians())) } - transform::ComputedOperation::InterpolateMatrix { .. } => { - // TODO: Convert InterpolateMatrix into a valid Matrix4D by the reference box. + transform::ComputedOperation::InterpolateMatrix { .. } | + transform::ComputedOperation::AccumulateMatrix { .. } => { + // TODO: Convert InterpolateMatrix/AccmulateMatrix into a valid Matrix4D by + // the reference box. Matrix4D::identity() } }; diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index b9b445ea5b6..50b354c7dbd 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2348,7 +2348,9 @@ fn static_assert() { ${transform_function_arm("Perspective", "perspective", ["length"])} _ => { // TODO: Convert ComputedOperation::InterpolateMatrix into - // eCSSKeyword_interpolatematrix. + // eCSSKeyword_interpolatematrix, and convert + // ComputedOperation::AccumulateMatrix into + // eCSSKeyword_accumulatematrix in the patch series. gecko_value.mUnit = structs::nsCSSUnit::eCSSUnit_None; } } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index cbb3296c042..2eae55e13cf 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -639,7 +639,31 @@ impl Animatable for AnimationValue { % endif % endfor _ => { - panic!("Expected weighted addition of computed values of the same \ + panic!("Expected addition of computed values of the same \ + property, got: {:?}, {:?}", self, other); + } + } + } + + fn accumulate(&self, other: &Self, count: u64) -> Result { + match (self, other) { + % for prop in data.longhands: + % if prop.animatable: + % if prop.animation_value_type == "discrete": + (&AnimationValue::${prop.camel_case}(_), + &AnimationValue::${prop.camel_case}(_)) => { + Err(()) + } + % else: + (&AnimationValue::${prop.camel_case}(ref from), + &AnimationValue::${prop.camel_case}(ref to)) => { + from.accumulate(to, count).map(AnimationValue::${prop.camel_case}) + } + % endif + % endif + % endfor + _ => { + panic!("Expected accumulation of computed values of the same \ property, got: {:?}, {:?}", self, other); } } @@ -1638,7 +1662,14 @@ fn build_identity_transform_list(list: &[TransformOperation]) -> Vec { result.push(TransformOperation::Rotate(0.0, 0.0, 1.0, Angle::zero())); } - TransformOperation::Perspective(..) => { + TransformOperation::Perspective(..) | + TransformOperation::AccumulateMatrix { .. } => { + // Perspective: We convert a perspective function into an equivalent + // ComputedMatrix, and then decompose/interpolate/recompose these matrices. + // AccumulateMatrix: We do interpolation on AccumulateMatrix by reading it as a + // ComputedMatrix (with layout information), and then do matrix interpolation. + // + // Therefore, we use an identity matrix to represent the identity transform list. // http://dev.w3.org/csswg/css-transforms/#identity-transform-function let identity = ComputedMatrix::identity(); result.push(TransformOperation::Matrix(identity)); @@ -2598,6 +2629,45 @@ impl Animatable for TransformList { } } + #[inline] + fn accumulate(&self, other: &Self, count: u64) -> Result { + match (&self.0, &other.0) { + (&Some(ref from_list), &Some(ref to_list)) => { + if can_interpolate_list(from_list, to_list) { + Ok(add_weighted_transform_lists(from_list, &to_list, count as f64, 1.0)) + } else { + use std::i32; + let result = vec![TransformOperation::AccumulateMatrix { + from_list: self.clone(), + to_list: other.clone(), + // For accumulation, we need to increase accumulation count for |other| if + // we do matrix decomposition/interpolation/recomposition on Gecko. After + // changing to Servo matrix decomposition/interpolation/recomposition, we + // don't need to increase one. I will remove this in the patch series. + count: cmp::min(count + 1, i32::MAX as u64) as i32 + }]; + Ok(TransformList(Some(result))) + } + } + (&Some(ref from_list), &None) => { + Ok(add_weighted_transform_lists(from_list, from_list, count as f64, 0.0)) + } + (&None, &Some(_)) => { + // If |self| is 'none' then we are calculating: + // + // none * |count| + |other| + // = none + |other| + // = |other| + // + // Hence the result is just |other|. + Ok(other.clone()) + } + _ => { + Ok(TransformList(None)) + } + } + } + #[inline] fn get_zero_value(&self) -> Option { Some(TransformList(None)) } } diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index f94c31227d4..2bf0c1b17f3 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -688,7 +688,7 @@ ${helpers.predefined_type("scroll-snap-coordinate", use app_units::Au; use values::computed::{LengthOrPercentageOrNumber as ComputedLoPoNumber, LengthOrNumber as ComputedLoN}; use values::computed::{LengthOrPercentage as ComputedLoP, Length as ComputedLength}; - use values::specified::{Angle, Length, LengthOrPercentage, Percentage}; + use values::specified::{Angle, Integer, Length, LengthOrPercentage, Percentage}; use values::specified::{LengthOrNumber, LengthOrPercentageOrNumber as LoPoNumber, Number}; use style_traits::ToCss; use style_traits::values::Css; @@ -762,14 +762,18 @@ ${helpers.predefined_type("scroll-snap-coordinate", // e.g. // [ InterpolateMatrix { from_list: [ InterpolateMatrix { ... }, // Scale(...) ], - // to_list: [ InterpolateMatrix { from_list: ..., - // to_list: [ InterpolateMatrix, + // to_list: [ AccumulateMatrix { from_list: ..., + // to_list: [ InterpolateMatrix, // ... ], - // progress: ... } ], + // count: ... } ], // progress: ... } ] InterpolateMatrix { from_list: T, to_list: T, progress: Percentage }, + // For accumulate operation of mismatched transform lists. + AccumulateMatrix { from_list: T, + to_list: T, + count: computed::Integer }, } #[derive(Clone, Debug, PartialEq)] @@ -853,6 +857,10 @@ ${helpers.predefined_type("scroll-snap-coordinate", InterpolateMatrix { from_list: SpecifiedValue, to_list: SpecifiedValue, progress: Percentage }, + /// A intermediate type for accumulation of mismatched transform lists. + AccumulateMatrix { from_list: SpecifiedValue, + to_list: SpecifiedValue, + count: Integer }, } impl ToCss for computed_value::T { @@ -1466,6 +1474,13 @@ ${helpers.predefined_type("scroll-snap-coordinate", progress: progress }); } + AccumulateMatrix { ref from_list, ref to_list, count } => { + result.push(computed_value::ComputedOperation::AccumulateMatrix { + from_list: from_list.to_computed_value(context), + to_list: to_list.to_computed_value(context), + count: count.value() + }); + } }; } @@ -1558,6 +1573,15 @@ ${helpers.predefined_type("scroll-snap-coordinate", progress: progress }); } + computed_value::ComputedOperation::AccumulateMatrix { ref from_list, + ref to_list, + count } => { + result.push(SpecifiedOperation::AccumulateMatrix { + from_list: SpecifiedValue::from_computed_value(from_list), + to_list: SpecifiedValue::from_computed_value(to_list), + count: Integer::new(count) + }); + } }; } result