diff options
author | Boris Chiou <boris.chiou@gmail.com> | 2019-11-15 19:38:24 +0000 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2019-11-30 20:45:00 +0100 |
commit | b420293a57305f36f3e1d6d2f9fbc8ee72bbd81a (patch) | |
tree | 88a833b5dd73322bb5b1ab45d1604ca16e50cb8d /components | |
parent | bb06ed72064812c841a39c900aa1c950e348c10a (diff) | |
download | servo-b420293a57305f36f3e1d6d2f9fbc8ee72bbd81a.tar.gz servo-b420293a57305f36f3e1d6d2f9fbc8ee72bbd81a.zip |
style: Treat 3d translate/scale as 2d if the value can be expressed as 2d.
For the individual transform properties if they spec a value that can be
expressed as 2d we treat as 2d and serialize accordingly.
We drop Translate::Translate and Scale::Scale, and then rename
Translate::Translate3D as Translate::Translate, Scale::Scale3D as
Scale::Scale. So now we use Translate::Translate to represent 2d and 3d
translation, and Scale::Scale to represent 2d and 3d scale. There is no
difference between 2d and 3d translate/scale in Gecko because we always
convert them into 3d format to layers (on the compositor thread), so this
change makes things simpler.
Differential Revision: https://phabricator.services.mozilla.com/D52931
Diffstat (limited to 'components')
-rw-r--r-- | components/style/values/animated/transform.rs | 201 | ||||
-rw-r--r-- | components/style/values/generics/transform.rs | 87 | ||||
-rw-r--r-- | components/style/values/specified/transform.rs | 15 |
3 files changed, 149 insertions, 154 deletions
diff --git a/components/style/values/animated/transform.rs b/components/style/values/animated/transform.rs index 9ac64c3f2a7..89bb3c0849d 100644 --- a/components/style/values/animated/transform.rs +++ b/components/style/values/animated/transform.rs @@ -139,10 +139,10 @@ impl ComputeSquaredDistance for MatrixDecomposed2D { const RAD_PER_DEG: f64 = std::f64::consts::PI / 180.0; let angle1 = self.angle as f64 * RAD_PER_DEG; let angle2 = other.angle as f64 * RAD_PER_DEG; - Ok(self.translate.compute_squared_distance(&other.translate)? + - self.scale.compute_squared_distance(&other.scale)? + - angle1.compute_squared_distance(&angle2)? + - self.matrix.compute_squared_distance(&other.matrix)?) + Ok(self.translate.compute_squared_distance(&other.translate)? + + self.scale.compute_squared_distance(&other.scale)? + + angle1.compute_squared_distance(&angle2)? + + self.matrix.compute_squared_distance(&other.matrix)?) } } @@ -316,9 +316,9 @@ impl ComputeSquaredDistance for Skew { // ComputeSquaredDistance manually. #[inline] fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { - Ok(self.0.atan().compute_squared_distance(&other.0.atan())? + - self.1.atan().compute_squared_distance(&other.1.atan())? + - self.2.atan().compute_squared_distance(&other.2.atan())?) + Ok(self.0.atan().compute_squared_distance(&other.0.atan())? + + self.1.atan().compute_squared_distance(&other.1.atan())? + + self.2.atan().compute_squared_distance(&other.2.atan())?) } } @@ -394,9 +394,9 @@ impl Animate for Quaternion { debug_assert!( // Doule EPSILON since both this_weight and other_weght have calculation errors // which are approximately equal to EPSILON. - (this_weight + other_weight - 1.0f64).abs() <= f64::EPSILON * 2.0 || - other_weight == 1.0f64 || - other_weight == 0.0f64, + (this_weight + other_weight - 1.0f64).abs() <= f64::EPSILON * 2.0 + || other_weight == 1.0f64 + || other_weight == 0.0f64, "animate should only be used for interpolating or accumulating transforms" ); @@ -830,17 +830,17 @@ fn is_matched_operation( second: &ComputedTransformOperation, ) -> bool { match (first, second) { - (&TransformOperation::Matrix(..), &TransformOperation::Matrix(..)) | - (&TransformOperation::Matrix3D(..), &TransformOperation::Matrix3D(..)) | - (&TransformOperation::Skew(..), &TransformOperation::Skew(..)) | - (&TransformOperation::SkewX(..), &TransformOperation::SkewX(..)) | - (&TransformOperation::SkewY(..), &TransformOperation::SkewY(..)) | - (&TransformOperation::Rotate(..), &TransformOperation::Rotate(..)) | - (&TransformOperation::Rotate3D(..), &TransformOperation::Rotate3D(..)) | - (&TransformOperation::RotateX(..), &TransformOperation::RotateX(..)) | - (&TransformOperation::RotateY(..), &TransformOperation::RotateY(..)) | - (&TransformOperation::RotateZ(..), &TransformOperation::RotateZ(..)) | - (&TransformOperation::Perspective(..), &TransformOperation::Perspective(..)) => true, + (&TransformOperation::Matrix(..), &TransformOperation::Matrix(..)) + | (&TransformOperation::Matrix3D(..), &TransformOperation::Matrix3D(..)) + | (&TransformOperation::Skew(..), &TransformOperation::Skew(..)) + | (&TransformOperation::SkewX(..), &TransformOperation::SkewX(..)) + | (&TransformOperation::SkewY(..), &TransformOperation::SkewY(..)) + | (&TransformOperation::Rotate(..), &TransformOperation::Rotate(..)) + | (&TransformOperation::Rotate3D(..), &TransformOperation::Rotate3D(..)) + | (&TransformOperation::RotateX(..), &TransformOperation::RotateX(..)) + | (&TransformOperation::RotateY(..), &TransformOperation::RotateY(..)) + | (&TransformOperation::RotateZ(..), &TransformOperation::RotateZ(..)) + | (&TransformOperation::Perspective(..), &TransformOperation::Perspective(..)) => true, // Match functions that have the same primitive transform function (a, b) if a.is_translate() && b.is_translate() => true, (a, b) if a.is_scale() && b.is_scale() => true, @@ -895,21 +895,21 @@ impl Animate for ComputedTransform { Procedure::Add => { debug_assert!(false, "Should have already dealt with add by the point"); return Err(()); - }, + } Procedure::Interpolate { progress } => { result.push(TransformOperation::InterpolateMatrix { from_list: Transform(this_remainder.to_vec().into()), to_list: Transform(other_remainder.to_vec().into()), progress: Percentage(progress as f32), }); - }, + } Procedure::Accumulate { count } => { result.push(TransformOperation::AccumulateMatrix { from_list: Transform(this_remainder.to_vec().into()), to_list: Transform(other_remainder.to_vec().into()), count: cmp::min(count, i32::max_value() as u64) as i32, }); - }, + } }, // If there is a remainder from just one list, then one list must be shorter but // completely match the type of the corresponding functions in the longer list. @@ -925,8 +925,8 @@ impl Animate for ComputedTransform { match transform { // We can't interpolate/accumulate ___Matrix types directly with a // matrix. Instead we need to wrap it in another ___Matrix type. - TransformOperation::AccumulateMatrix { .. } | - TransformOperation::InterpolateMatrix { .. } => { + TransformOperation::AccumulateMatrix { .. } + | TransformOperation::InterpolateMatrix { .. } => { let transform_list = Transform(vec![transform.clone()].into()); let identity_list = Transform(vec![identity].into()); let (from_list, to_list) = if fill_right { @@ -943,7 +943,7 @@ impl Animate for ComputedTransform { to_list, progress: Percentage(progress as f32), }) - }, + } Procedure::Accumulate { count } => { Ok(TransformOperation::AccumulateMatrix { from_list, @@ -951,9 +951,9 @@ impl Animate for ComputedTransform { count: cmp::min(count, i32::max_value() as u64) as i32, }) - }, + } } - }, + } _ => { let (lhs, rhs) = if fill_right { (transform, &identity) @@ -961,13 +961,13 @@ impl Animate for ComputedTransform { (&identity, transform) }; lhs.animate(rhs, procedure) - }, + } } }) .collect::<Result<Vec<_>, _>>()?, ); - }, - (None, None) => {}, + } + (None, None) => {} } Ok(Transform(result.into())) @@ -999,10 +999,10 @@ impl Animate for ComputedTransformOperation { Ok(TransformOperation::Matrix3D( this.animate(other, procedure)?, )) - }, + } (&TransformOperation::Matrix(ref this), &TransformOperation::Matrix(ref other)) => { Ok(TransformOperation::Matrix(this.animate(other, procedure)?)) - }, + } ( &TransformOperation::Skew(ref fx, ref fy), &TransformOperation::Skew(ref tx, ref ty), @@ -1012,10 +1012,10 @@ impl Animate for ComputedTransformOperation { )), (&TransformOperation::SkewX(ref f), &TransformOperation::SkewX(ref t)) => { Ok(TransformOperation::SkewX(f.animate(t, procedure)?)) - }, + } (&TransformOperation::SkewY(ref f), &TransformOperation::SkewY(ref t)) => { Ok(TransformOperation::SkewY(f.animate(t, procedure)?)) - }, + } ( &TransformOperation::Translate3D(ref fx, ref fy, ref fz), &TransformOperation::Translate3D(ref tx, ref ty, ref tz), @@ -1033,13 +1033,13 @@ impl Animate for ComputedTransformOperation { )), (&TransformOperation::TranslateX(ref f), &TransformOperation::TranslateX(ref t)) => { Ok(TransformOperation::TranslateX(f.animate(t, procedure)?)) - }, + } (&TransformOperation::TranslateY(ref f), &TransformOperation::TranslateY(ref t)) => { Ok(TransformOperation::TranslateY(f.animate(t, procedure)?)) - }, + } (&TransformOperation::TranslateZ(ref f), &TransformOperation::TranslateZ(ref t)) => { Ok(TransformOperation::TranslateZ(f.animate(t, procedure)?)) - }, + } ( &TransformOperation::Scale3D(ref fx, ref fy, ref fz), &TransformOperation::Scale3D(ref tx, ref ty, ref tz), @@ -1072,25 +1072,25 @@ impl Animate for ComputedTransformOperation { .animate(&Rotate::Rotate3D(tx, ty, tz, ta), procedure)?; let (fx, fy, fz, fa) = ComputedRotate::resolve(&animated); Ok(TransformOperation::Rotate3D(fx, fy, fz, fa)) - }, + } (&TransformOperation::RotateX(fa), &TransformOperation::RotateX(ta)) => { Ok(TransformOperation::RotateX(fa.animate(&ta, procedure)?)) - }, + } (&TransformOperation::RotateY(fa), &TransformOperation::RotateY(ta)) => { Ok(TransformOperation::RotateY(fa.animate(&ta, procedure)?)) - }, + } (&TransformOperation::RotateZ(fa), &TransformOperation::RotateZ(ta)) => { Ok(TransformOperation::RotateZ(fa.animate(&ta, procedure)?)) - }, + } (&TransformOperation::Rotate(fa), &TransformOperation::Rotate(ta)) => { Ok(TransformOperation::Rotate(fa.animate(&ta, procedure)?)) - }, + } (&TransformOperation::Rotate(fa), &TransformOperation::RotateZ(ta)) => { Ok(TransformOperation::Rotate(fa.animate(&ta, procedure)?)) - }, + } (&TransformOperation::RotateZ(fa), &TransformOperation::Rotate(ta)) => { Ok(TransformOperation::Rotate(fa.animate(&ta, procedure)?)) - }, + } ( &TransformOperation::Perspective(ref fd), &TransformOperation::Perspective(ref td), @@ -1120,13 +1120,13 @@ impl Animate for ComputedTransformOperation { Ok(TransformOperation::Perspective(CSSPixelLength::new( used_value, ))) - }, + } _ if self.is_translate() && other.is_translate() => self .to_translate_3d() .animate(&other.to_translate_3d(), procedure), _ if self.is_scale() && other.is_scale() => { self.to_scale_3d().animate(&other.to_scale_3d(), procedure) - }, + } _ if self.is_rotate() && other.is_rotate() => self .to_rotate_3d() .animate(&other.to_rotate_3d(), procedure), @@ -1144,20 +1144,20 @@ impl ComputeSquaredDistance for ComputedTransformOperation { match (self, other) { (&TransformOperation::Matrix3D(ref this), &TransformOperation::Matrix3D(ref other)) => { this.compute_squared_distance(other) - }, + } (&TransformOperation::Matrix(ref this), &TransformOperation::Matrix(ref other)) => { let this: Matrix3D = (*this).into(); let other: Matrix3D = (*other).into(); this.compute_squared_distance(&other) - }, + } ( &TransformOperation::Skew(ref fx, ref fy), &TransformOperation::Skew(ref tx, ref ty), ) => Ok(fx.compute_squared_distance(&tx)? + fy.compute_squared_distance(&ty)?), - (&TransformOperation::SkewX(ref f), &TransformOperation::SkewX(ref t)) | - (&TransformOperation::SkewY(ref f), &TransformOperation::SkewY(ref t)) => { + (&TransformOperation::SkewX(ref f), &TransformOperation::SkewX(ref t)) + | (&TransformOperation::SkewY(ref f), &TransformOperation::SkewY(ref t)) => { f.compute_squared_distance(&t) - }, + } ( &TransformOperation::Translate3D(ref fx, ref fy, ref fz), &TransformOperation::Translate3D(ref tx, ref ty, ref tz), @@ -1173,33 +1173,33 @@ impl ComputeSquaredDistance for ComputedTransformOperation { let tx = tx.length_component().px(); let ty = ty.length_component().px(); - Ok(fx.compute_squared_distance(&tx)? + - fy.compute_squared_distance(&ty)? + - fz.compute_squared_distance(&tz)?) - }, + Ok(fx.compute_squared_distance(&tx)? + + fy.compute_squared_distance(&ty)? + + fz.compute_squared_distance(&tz)?) + } ( &TransformOperation::Scale3D(ref fx, ref fy, ref fz), &TransformOperation::Scale3D(ref tx, ref ty, ref tz), - ) => Ok(fx.compute_squared_distance(&tx)? + - fy.compute_squared_distance(&ty)? + - fz.compute_squared_distance(&tz)?), + ) => Ok(fx.compute_squared_distance(&tx)? + + fy.compute_squared_distance(&ty)? + + fz.compute_squared_distance(&tz)?), ( &TransformOperation::Rotate3D(fx, fy, fz, fa), &TransformOperation::Rotate3D(tx, ty, tz, ta), ) => Rotate::Rotate3D(fx, fy, fz, fa) .compute_squared_distance(&Rotate::Rotate3D(tx, ty, tz, ta)), - (&TransformOperation::RotateX(fa), &TransformOperation::RotateX(ta)) | - (&TransformOperation::RotateY(fa), &TransformOperation::RotateY(ta)) | - (&TransformOperation::RotateZ(fa), &TransformOperation::RotateZ(ta)) | - (&TransformOperation::Rotate(fa), &TransformOperation::Rotate(ta)) => { + (&TransformOperation::RotateX(fa), &TransformOperation::RotateX(ta)) + | (&TransformOperation::RotateY(fa), &TransformOperation::RotateY(ta)) + | (&TransformOperation::RotateZ(fa), &TransformOperation::RotateZ(ta)) + | (&TransformOperation::Rotate(fa), &TransformOperation::Rotate(ta)) => { fa.compute_squared_distance(&ta) - }, + } ( &TransformOperation::Perspective(ref fd), &TransformOperation::Perspective(ref td), ) => fd.compute_squared_distance(td), - (&TransformOperation::Perspective(ref p), &TransformOperation::Matrix3D(ref m)) | - (&TransformOperation::Matrix3D(ref m), &TransformOperation::Perspective(ref p)) => { + (&TransformOperation::Perspective(ref p), &TransformOperation::Matrix3D(ref m)) + | (&TransformOperation::Matrix3D(ref m), &TransformOperation::Perspective(ref p)) => { // FIXME(emilio): Is this right? Why interpolating this with // Perspective but not with anything else? let mut p_matrix = Matrix3D::identity(); @@ -1207,7 +1207,7 @@ impl ComputeSquaredDistance for ComputedTransformOperation { p_matrix.m34 = -1. / p.px(); } p_matrix.compute_squared_distance(&m) - }, + } // Gecko cross-interpolates amongst all translate and all scale // functions (See ToPrimitive in layout/style/StyleAnimationValue.cpp) // without falling back to InterpolateMatrix @@ -1256,7 +1256,7 @@ impl Animate for ComputedRotate { fz, fa.animate(&Angle::zero(), procedure)?, )) - }, + } (&Rotate::None, &Rotate::Rotate3D(tx, ty, tz, ta)) => { // No need to normalize `none`, so animate angle directly. Ok(Rotate::Rotate3D( @@ -1265,7 +1265,7 @@ impl Animate for ComputedRotate { tz, Angle::zero().animate(&ta, procedure)?, )) - }, + } (&Rotate::Rotate3D(_, ..), _) | (_, &Rotate::Rotate3D(_, ..)) => { let (from, to) = (self.resolve(), other.resolve()); let (mut fx, mut fy, mut fz, fa) = @@ -1301,12 +1301,12 @@ impl Animate for ComputedRotate { ); Ok(Rotate::Rotate3D(x, y, z, Angle::from_radians(angle))) - }, + } (&Rotate::Rotate(_), _) | (_, &Rotate::Rotate(_)) => { // If this is a 2D rotation, we just animate the <angle> let (from, to) = (self.resolve().3, other.resolve().3); Ok(Rotate::Rotate(from.animate(&to, procedure)?)) - }, + } } } } @@ -1316,10 +1316,10 @@ impl ComputeSquaredDistance for ComputedRotate { fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { match (self, other) { (&Rotate::None, &Rotate::None) => Ok(SquaredDistance::from_sqrt(0.)), - (&Rotate::Rotate3D(_, _, _, a), &Rotate::None) | - (&Rotate::None, &Rotate::Rotate3D(_, _, _, a)) => { + (&Rotate::Rotate3D(_, _, _, a), &Rotate::None) + | (&Rotate::None, &Rotate::Rotate3D(_, _, _, a)) => { a.compute_squared_distance(&Angle::zero()) - }, + } (&Rotate::Rotate3D(_, ..), _) | (_, &Rotate::Rotate3D(_, ..)) => { let (from, to) = (self.resolve(), other.resolve()); let (mut fx, mut fy, mut fz, angle1) = @@ -1346,7 +1346,7 @@ impl ComputeSquaredDistance for ComputedRotate { let q2 = Quaternion::from_direction_and_angle(&v2, angle2.radians64()); q1.compute_squared_distance(&q2) } - }, + } (&Rotate::Rotate(_), _) | (_, &Rotate::Rotate(_)) => self .resolve() .3 @@ -1368,8 +1368,7 @@ impl ComputedTranslate { LengthPercentage::zero(), Length::zero(), ), - Translate::Translate3D(tx, ty, tz) => (tx, ty, tz), - Translate::Translate(tx, ty) => (tx, ty, Length::zero()), + Translate::Translate(tx, ty, tz) => (tx, ty, tz), } } } @@ -1379,21 +1378,14 @@ impl Animate for ComputedTranslate { fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { match (self, other) { (&Translate::None, &Translate::None) => Ok(Translate::None), - (&Translate::Translate3D(_, ..), _) | (_, &Translate::Translate3D(_, ..)) => { - let (from, to) = (self.resolve(), other.resolve()); - Ok(Translate::Translate3D( - from.0.animate(&to.0, procedure)?, - from.1.animate(&to.1, procedure)?, - from.2.animate(&to.2, procedure)?, - )) - }, (&Translate::Translate(_, ..), _) | (_, &Translate::Translate(_, ..)) => { let (from, to) = (self.resolve(), other.resolve()); Ok(Translate::Translate( from.0.animate(&to.0, procedure)?, from.1.animate(&to.1, procedure)?, + from.2.animate(&to.2, procedure)?, )) - }, + } } } } @@ -1402,9 +1394,9 @@ impl ComputeSquaredDistance for ComputedTranslate { #[inline] fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { let (from, to) = (self.resolve(), other.resolve()); - Ok(from.0.compute_squared_distance(&to.0)? + - from.1.compute_squared_distance(&to.1)? + - from.2.compute_squared_distance(&to.2)?) + Ok(from.0.compute_squared_distance(&to.0)? + + from.1.compute_squared_distance(&to.1)? + + from.2.compute_squared_distance(&to.2)?) } } @@ -1417,8 +1409,7 @@ impl ComputedScale { // Unspecified scales default to 1 match *self { Scale::None => (1.0, 1.0, 1.0), - Scale::Scale3D(sx, sy, sz) => (sx, sy, sz), - Scale::Scale(sx, sy) => (sx, sy, 1.), + Scale::Scale(sx, sy, sz) => (sx, sy, sz), } } } @@ -1428,7 +1419,7 @@ impl Animate for ComputedScale { fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { match (self, other) { (&Scale::None, &Scale::None) => Ok(Scale::None), - (&Scale::Scale3D(_, ..), _) | (_, &Scale::Scale3D(_, ..)) => { + (&Scale::Scale(_, ..), _) | (_, &Scale::Scale(_, ..)) => { let (from, to) = (self.resolve(), other.resolve()); // For transform lists, we add by appending to the list of // transform functions. However, ComputedScale cannot be @@ -1436,26 +1427,14 @@ impl Animate for ComputedScale { // result here. if procedure == Procedure::Add { // scale(x1,y1,z1)*scale(x2,y2,z2) = scale(x1*x2, y1*y2, z1*z2) - return Ok(Scale::Scale3D(from.0 * to.0, from.1 * to.1, from.2 * to.2)); - } - Ok(Scale::Scale3D( - animate_multiplicative_factor(from.0, to.0, procedure)?, - animate_multiplicative_factor(from.1, to.1, procedure)?, - animate_multiplicative_factor(from.2, to.2, procedure)?, - )) - }, - (&Scale::Scale(_, ..), _) | (_, &Scale::Scale(_, ..)) => { - let (from, to) = (self.resolve(), other.resolve()); - // As with Scale3D, addition needs special handling. - if procedure == Procedure::Add { - // scale(x1,y1)*scale(x2,y2) = scale(x1*x2, y1*y2) - return Ok(Scale::Scale(from.0 * to.0, from.1 * to.1)); + return Ok(Scale::Scale(from.0 * to.0, from.1 * to.1, from.2 * to.2)); } Ok(Scale::Scale( animate_multiplicative_factor(from.0, to.0, procedure)?, animate_multiplicative_factor(from.1, to.1, procedure)?, + animate_multiplicative_factor(from.2, to.2, procedure)?, )) - }, + } } } } @@ -1464,8 +1443,8 @@ impl ComputeSquaredDistance for ComputedScale { #[inline] fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { let (from, to) = (self.resolve(), other.resolve()); - Ok(from.0.compute_squared_distance(&to.0)? + - from.1.compute_squared_distance(&to.1)? + - from.2.compute_squared_distance(&to.2)?) + Ok(from.0.compute_squared_distance(&to.0)? + + from.1.compute_squared_distance(&to.1)? + + from.2.compute_squared_distance(&to.2)?) } } diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 4a8dc7f63fa..cc401966a97 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -303,7 +303,7 @@ where match *self { Translate(..) | Translate3D(..) | TranslateX(..) | TranslateY(..) | TranslateZ(..) => { true - }, + } _ => false, } } @@ -415,8 +415,8 @@ where fn is_3d(&self) -> bool { use self::TransformOperation::*; match *self { - Translate3D(..) | TranslateZ(..) | Rotate3D(..) | RotateX(..) | RotateY(..) | - RotateZ(..) | Scale3D(..) | ScaleZ(..) | Perspective(..) | Matrix3D(..) => true, + Translate3D(..) | TranslateZ(..) | Rotate3D(..) | RotateX(..) | RotateY(..) + | RotateZ(..) | Scale3D(..) | ScaleZ(..) | Perspective(..) | Matrix3D(..) => true, _ => false, } } @@ -444,23 +444,23 @@ where az as f64, euclid::Angle::radians(theta), ) - }, + } RotateX(theta) => { let theta = euclid::Angle::radians(TWO_PI - theta.radians64()); Transform3D::create_rotation(1., 0., 0., theta) - }, + } RotateY(theta) => { let theta = euclid::Angle::radians(TWO_PI - theta.radians64()); Transform3D::create_rotation(0., 1., 0., theta) - }, + } RotateZ(theta) | Rotate(theta) => { let theta = euclid::Angle::radians(TWO_PI - theta.radians64()); Transform3D::create_rotation(0., 0., 1., theta) - }, + } Perspective(ref d) => { let m = create_perspective_matrix(d.to_pixel_length(None)?); m.cast() - }, + } Scale3D(sx, sy, sz) => Transform3D::create_scale(sx.into(), sy.into(), sz.into()), Scale(sx, sy) => Transform3D::create_scale(sx.into(), sy.into(), 1.), ScaleX(s) => Transform3D::create_scale(s.into(), 1., 1.), @@ -470,23 +470,23 @@ where let tx = tx.to_pixel_length(reference_width)? as f64; let ty = ty.to_pixel_length(reference_height)? as f64; Transform3D::create_translation(tx, ty, tz.to_pixel_length(None)? as f64) - }, + } Translate(ref tx, ref ty) => { let tx = tx.to_pixel_length(reference_width)? as f64; let ty = ty.to_pixel_length(reference_height)? as f64; Transform3D::create_translation(tx, ty, 0.) - }, + } TranslateX(ref t) => { let t = t.to_pixel_length(reference_width)? as f64; Transform3D::create_translation(t, 0., 0.) - }, + } TranslateY(ref t) => { let t = t.to_pixel_length(reference_height)? as f64; Transform3D::create_translation(0., t, 0.) - }, + } TranslateZ(ref z) => { Transform3D::create_translation(0., 0., z.to_pixel_length(None)? as f64) - }, + } Skew(theta_x, theta_y) => Transform3D::create_skew( euclid::Angle::radians(theta_x.radians64()), euclid::Angle::radians(theta_y.radians64()), @@ -509,7 +509,7 @@ where // return an identity matrix. // Note: DOMMatrix doesn't go into this arm. Transform3D::identity() - }, + } }; Ok(matrix) } @@ -676,7 +676,7 @@ where } dest.write_char(' ')?; angle.to_css(dest) - }, + } } } } @@ -700,40 +700,52 @@ where pub enum GenericScale<Number> { /// 'none' None, - /// '<number>{1,2}' - Scale(Number, Number), - /// '<number>{3}' - Scale3D(Number, Number, Number), + /// '<number>{1,3}' + Scale(Number, Number, Number), } pub use self::GenericScale as Scale; -impl<Number: ToCss + PartialEq> ToCss for Scale<Number> { +impl<Number> ToCss for Scale<Number> +where + Number: ToCss + PartialEq + Copy, + f32: From<Number>, +{ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write, + f32: From<Number>, { match *self { Scale::None => dest.write_str("none"), - Scale::Scale(ref x, ref y) => { + Scale::Scale(ref x, ref y, ref z) => { x.to_css(dest)?; - if x != y { + + let is_3d = f32::from(*z) != 1.0; + if is_3d || x != y { dest.write_char(' ')?; y.to_css(dest)?; } + + if is_3d { + dest.write_char(' ')?; + z.to_css(dest)?; + } Ok(()) - }, - Scale::Scale3D(ref x, ref y, ref z) => { - x.to_css(dest)?; - dest.write_char(' ')?; - y.to_css(dest)?; - dest.write_char(' ')?; - z.to_css(dest) - }, + } } } } +#[inline] +fn y_axis_and_z_axis_are_zero<LengthPercentage: Zero, Length: Zero>( + _: &LengthPercentage, + y: &LengthPercentage, + z: &Length, +) -> bool { + y.is_zero() && z.is_zero() +} + #[derive( Clone, Debug, @@ -755,25 +767,24 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> { /// or two values (per usual, if the second value is 0px, the default, it must /// be omitted when serializing). /// -/// If a 3d translation is specified, all three values must be serialized. -/// -/// We don't omit the 3rd component even if it is 0px for now, and the -/// related spec issue is https://github.com/w3c/csswg-drafts/issues/3305 +/// If a 3d translation is specified and the value can be expressed as 2d, we treat as 2d and +/// serialize accoringly. Otherwise, we serialize all three values. +/// https://github.com/w3c/csswg-drafts/issues/3305 /// /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms> pub enum GenericTranslate<LengthPercentage, Length> where LengthPercentage: Zero, + Length: Zero, { /// 'none' None, - /// '<length-percentage>' or '<length-percentage> <length-percentage>' + /// <length-percentage> [ <length-percentage> <length>? ]? Translate( LengthPercentage, - #[css(skip_if = "Zero::is_zero")] LengthPercentage, + #[css(contextual_skip_if = "y_axis_and_z_axis_are_zero")] LengthPercentage, + #[css(skip_if = "Zero::is_zero")] Length, ), - /// '<length-percentage> <length-percentage> <length>' - Translate3D(LengthPercentage, LengthPercentage, Length), } pub use self::GenericTranslate as Translate; diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index 157c6504856..6a33b665463 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -421,17 +421,22 @@ impl Parse for Translate { if let Ok(ty) = input.try(|i| specified::LengthPercentage::parse(context, i)) { if let Ok(tz) = input.try(|i| specified::Length::parse(context, i)) { // 'translate: <length-percentage> <length-percentage> <length>' - return Ok(generic::Translate::Translate3D(tx, ty, tz)); + return Ok(generic::Translate::Translate(tx, ty, tz)); } // translate: <length-percentage> <length-percentage>' - return Ok(generic::Translate::Translate(tx, ty)); + return Ok(generic::Translate::Translate( + tx, + ty, + specified::Length::zero(), + )); } // 'translate: <length-percentage> ' Ok(generic::Translate::Translate( tx, specified::LengthPercentage::zero(), + specified::Length::zero(), )) } } @@ -452,14 +457,14 @@ impl Parse for Scale { if let Ok(sy) = input.try(|i| Number::parse(context, i)) { if let Ok(sz) = input.try(|i| Number::parse(context, i)) { // 'scale: <number> <number> <number>' - return Ok(generic::Scale::Scale3D(sx, sy, sz)); + return Ok(generic::Scale::Scale(sx, sy, sz)); } // 'scale: <number> <number>' - return Ok(generic::Scale::Scale(sx, sy)); + return Ok(generic::Scale::Scale(sx, sy, Number::new(1.0))); } // 'scale: <number>' - Ok(generic::Scale::Scale(sx, sx)) + Ok(generic::Scale::Scale(sx, sx, Number::new(1.0))) } } |