From 313f7d86db2b67ce50cfea77b1915eb0473fcc40 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Wed, 31 May 2017 15:38:14 +0800 Subject: [PATCH] Define ComputedOperation::AccmulateMatrix. If we set the composite operation to accumulate, we may need to accumulate two mismatched transform lists, and then to interpolate them. In order to accumulate two mismatched transform lists, we also need the reference box information, so use the same idea as that for interpolation. i.e. use AccmulateMatrix to store it temporarily, and convert it into matrix later. --- components/layout/fragment.rs | 6 +- components/style/properties/gecko.mako.rs | 4 +- .../helpers/animated_properties.mako.rs | 74 ++++++++++++++++++- .../style/properties/longhand/box.mako.rs | 32 +++++++- 4 files changed, 107 insertions(+), 9 deletions(-) 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