tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

transform.rs (23514B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      4 
      5 //! Computed types for CSS values that are related to transformations.
      6 
      7 use super::CSSFloat;
      8 use crate::values::animated::transform::{Perspective, Scale3D, Translate3D};
      9 use crate::values::animated::ToAnimatedZero;
     10 use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
     11 use crate::values::generics::transform as generic;
     12 use crate::Zero;
     13 use euclid::default::{Transform3D, Vector3D};
     14 
     15 pub use crate::values::generics::transform::TransformStyle;
     16 pub use crate::values::specified::transform::TransformBox;
     17 
     18 /// A single operation in a computed CSS `transform`
     19 pub type TransformOperation =
     20    generic::GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>;
     21 /// A computed CSS `transform`
     22 pub type Transform = generic::GenericTransform<TransformOperation>;
     23 
     24 /// The computed value of a CSS `<transform-origin>`
     25 pub type TransformOrigin =
     26    generic::GenericTransformOrigin<LengthPercentage, LengthPercentage, Length>;
     27 
     28 /// The computed value of the `perspective()` transform function.
     29 pub type PerspectiveFunction = generic::PerspectiveFunction<Length>;
     30 
     31 /// A vector to represent the direction vector (rotate axis) for Rotate3D.
     32 pub type DirectionVector = Vector3D<CSSFloat>;
     33 
     34 impl TransformOrigin {
     35    /// Returns the initial computed value for `transform-origin`.
     36    #[inline]
     37    pub fn initial_value() -> Self {
     38        Self::new(
     39            LengthPercentage::new_percent(Percentage(0.5)),
     40            LengthPercentage::new_percent(Percentage(0.5)),
     41            Length::new(0.),
     42        )
     43    }
     44 }
     45 
     46 /// computed value of matrix3d()
     47 pub type Matrix3D = generic::Matrix3D<Number>;
     48 
     49 /// computed value of matrix()
     50 pub type Matrix = generic::Matrix<Number>;
     51 
     52 // we rustfmt_skip here because we want the matrices to look like
     53 // matrices instead of being split across lines
     54 #[cfg_attr(rustfmt, rustfmt_skip)]
     55 impl Matrix3D {
     56    /// Get an identity matrix
     57    #[inline]
     58    pub fn identity() -> Self {
     59        Self {
     60            m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
     61            m21: 0.0, m22: 1.0, m23: 0.0, m24: 0.0,
     62            m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
     63            m41: 0., m42: 0., m43: 0., m44: 1.0
     64        }
     65    }
     66 
     67    /// Convert to a 2D Matrix
     68    #[inline]
     69    pub fn into_2d(self) -> Result<Matrix, ()> {
     70        if self.m13 == 0. && self.m23 == 0. &&
     71           self.m31 == 0. && self.m32 == 0. &&
     72           self.m33 == 1. && self.m34 == 0. &&
     73           self.m14 == 0. && self.m24 == 0. &&
     74           self.m43 == 0. && self.m44 == 1. {
     75            Ok(Matrix {
     76                a: self.m11, c: self.m21, e: self.m41,
     77                b: self.m12, d: self.m22, f: self.m42,
     78            })
     79        } else {
     80            Err(())
     81        }
     82    }
     83 
     84    /// Return true if this has 3D components.
     85    #[inline]
     86    pub fn is_3d(&self) -> bool {
     87        self.m13 != 0.0 || self.m14 != 0.0 ||
     88        self.m23 != 0.0 || self.m24 != 0.0 ||
     89        self.m31 != 0.0 || self.m32 != 0.0 ||
     90        self.m33 != 1.0 || self.m34 != 0.0 ||
     91        self.m43 != 0.0 || self.m44 != 1.0
     92    }
     93 
     94    /// Return determinant value.
     95    #[inline]
     96    pub fn determinant(&self) -> CSSFloat {
     97        self.m14 * self.m23 * self.m32 * self.m41 -
     98        self.m13 * self.m24 * self.m32 * self.m41 -
     99        self.m14 * self.m22 * self.m33 * self.m41 +
    100        self.m12 * self.m24 * self.m33 * self.m41 +
    101        self.m13 * self.m22 * self.m34 * self.m41 -
    102        self.m12 * self.m23 * self.m34 * self.m41 -
    103        self.m14 * self.m23 * self.m31 * self.m42 +
    104        self.m13 * self.m24 * self.m31 * self.m42 +
    105        self.m14 * self.m21 * self.m33 * self.m42 -
    106        self.m11 * self.m24 * self.m33 * self.m42 -
    107        self.m13 * self.m21 * self.m34 * self.m42 +
    108        self.m11 * self.m23 * self.m34 * self.m42 +
    109        self.m14 * self.m22 * self.m31 * self.m43 -
    110        self.m12 * self.m24 * self.m31 * self.m43 -
    111        self.m14 * self.m21 * self.m32 * self.m43 +
    112        self.m11 * self.m24 * self.m32 * self.m43 +
    113        self.m12 * self.m21 * self.m34 * self.m43 -
    114        self.m11 * self.m22 * self.m34 * self.m43 -
    115        self.m13 * self.m22 * self.m31 * self.m44 +
    116        self.m12 * self.m23 * self.m31 * self.m44 +
    117        self.m13 * self.m21 * self.m32 * self.m44 -
    118        self.m11 * self.m23 * self.m32 * self.m44 -
    119        self.m12 * self.m21 * self.m33 * self.m44 +
    120        self.m11 * self.m22 * self.m33 * self.m44
    121    }
    122 
    123    /// Transpose a matrix.
    124    #[inline]
    125    pub fn transpose(&self) -> Self {
    126        Self {
    127            m11: self.m11, m12: self.m21, m13: self.m31, m14: self.m41,
    128            m21: self.m12, m22: self.m22, m23: self.m32, m24: self.m42,
    129            m31: self.m13, m32: self.m23, m33: self.m33, m34: self.m43,
    130            m41: self.m14, m42: self.m24, m43: self.m34, m44: self.m44,
    131        }
    132    }
    133 
    134    /// Return inverse matrix.
    135    pub fn inverse(&self) -> Result<Matrix3D, ()> {
    136        let mut det = self.determinant();
    137 
    138        if det == 0.0 {
    139            return Err(());
    140        }
    141 
    142        det = 1.0 / det;
    143        let x = Matrix3D {
    144            m11: det *
    145            (self.m23 * self.m34 * self.m42 - self.m24 * self.m33 * self.m42 +
    146             self.m24 * self.m32 * self.m43 - self.m22 * self.m34 * self.m43 -
    147             self.m23 * self.m32 * self.m44 + self.m22 * self.m33 * self.m44),
    148            m12: det *
    149            (self.m14 * self.m33 * self.m42 - self.m13 * self.m34 * self.m42 -
    150             self.m14 * self.m32 * self.m43 + self.m12 * self.m34 * self.m43 +
    151             self.m13 * self.m32 * self.m44 - self.m12 * self.m33 * self.m44),
    152            m13: det *
    153            (self.m13 * self.m24 * self.m42 - self.m14 * self.m23 * self.m42 +
    154             self.m14 * self.m22 * self.m43 - self.m12 * self.m24 * self.m43 -
    155             self.m13 * self.m22 * self.m44 + self.m12 * self.m23 * self.m44),
    156            m14: det *
    157            (self.m14 * self.m23 * self.m32 - self.m13 * self.m24 * self.m32 -
    158             self.m14 * self.m22 * self.m33 + self.m12 * self.m24 * self.m33 +
    159             self.m13 * self.m22 * self.m34 - self.m12 * self.m23 * self.m34),
    160            m21: det *
    161            (self.m24 * self.m33 * self.m41 - self.m23 * self.m34 * self.m41 -
    162             self.m24 * self.m31 * self.m43 + self.m21 * self.m34 * self.m43 +
    163             self.m23 * self.m31 * self.m44 - self.m21 * self.m33 * self.m44),
    164            m22: det *
    165            (self.m13 * self.m34 * self.m41 - self.m14 * self.m33 * self.m41 +
    166             self.m14 * self.m31 * self.m43 - self.m11 * self.m34 * self.m43 -
    167             self.m13 * self.m31 * self.m44 + self.m11 * self.m33 * self.m44),
    168            m23: det *
    169            (self.m14 * self.m23 * self.m41 - self.m13 * self.m24 * self.m41 -
    170             self.m14 * self.m21 * self.m43 + self.m11 * self.m24 * self.m43 +
    171             self.m13 * self.m21 * self.m44 - self.m11 * self.m23 * self.m44),
    172            m24: det *
    173            (self.m13 * self.m24 * self.m31 - self.m14 * self.m23 * self.m31 +
    174             self.m14 * self.m21 * self.m33 - self.m11 * self.m24 * self.m33 -
    175             self.m13 * self.m21 * self.m34 + self.m11 * self.m23 * self.m34),
    176            m31: det *
    177            (self.m22 * self.m34 * self.m41 - self.m24 * self.m32 * self.m41 +
    178             self.m24 * self.m31 * self.m42 - self.m21 * self.m34 * self.m42 -
    179             self.m22 * self.m31 * self.m44 + self.m21 * self.m32 * self.m44),
    180            m32: det *
    181            (self.m14 * self.m32 * self.m41 - self.m12 * self.m34 * self.m41 -
    182             self.m14 * self.m31 * self.m42 + self.m11 * self.m34 * self.m42 +
    183             self.m12 * self.m31 * self.m44 - self.m11 * self.m32 * self.m44),
    184            m33: det *
    185            (self.m12 * self.m24 * self.m41 - self.m14 * self.m22 * self.m41 +
    186             self.m14 * self.m21 * self.m42 - self.m11 * self.m24 * self.m42 -
    187             self.m12 * self.m21 * self.m44 + self.m11 * self.m22 * self.m44),
    188            m34: det *
    189            (self.m14 * self.m22 * self.m31 - self.m12 * self.m24 * self.m31 -
    190             self.m14 * self.m21 * self.m32 + self.m11 * self.m24 * self.m32 +
    191             self.m12 * self.m21 * self.m34 - self.m11 * self.m22 * self.m34),
    192            m41: det *
    193            (self.m23 * self.m32 * self.m41 - self.m22 * self.m33 * self.m41 -
    194             self.m23 * self.m31 * self.m42 + self.m21 * self.m33 * self.m42 +
    195             self.m22 * self.m31 * self.m43 - self.m21 * self.m32 * self.m43),
    196            m42: det *
    197            (self.m12 * self.m33 * self.m41 - self.m13 * self.m32 * self.m41 +
    198             self.m13 * self.m31 * self.m42 - self.m11 * self.m33 * self.m42 -
    199             self.m12 * self.m31 * self.m43 + self.m11 * self.m32 * self.m43),
    200            m43: det *
    201            (self.m13 * self.m22 * self.m41 - self.m12 * self.m23 * self.m41 -
    202             self.m13 * self.m21 * self.m42 + self.m11 * self.m23 * self.m42 +
    203             self.m12 * self.m21 * self.m43 - self.m11 * self.m22 * self.m43),
    204            m44: det *
    205            (self.m12 * self.m23 * self.m31 - self.m13 * self.m22 * self.m31 +
    206             self.m13 * self.m21 * self.m32 - self.m11 * self.m23 * self.m32 -
    207             self.m12 * self.m21 * self.m33 + self.m11 * self.m22 * self.m33),
    208        };
    209 
    210        Ok(x)
    211    }
    212 
    213    /// Multiply `pin * self`.
    214    #[inline]
    215    pub fn pre_mul_point4(&self, pin: &[f32; 4]) -> [f32; 4] {
    216        [
    217            pin[0] * self.m11 + pin[1] * self.m21 + pin[2] * self.m31 + pin[3] * self.m41,
    218            pin[0] * self.m12 + pin[1] * self.m22 + pin[2] * self.m32 + pin[3] * self.m42,
    219            pin[0] * self.m13 + pin[1] * self.m23 + pin[2] * self.m33 + pin[3] * self.m43,
    220            pin[0] * self.m14 + pin[1] * self.m24 + pin[2] * self.m34 + pin[3] * self.m44,
    221        ]
    222    }
    223 
    224    /// Return the multiplication of two 4x4 matrices.
    225    #[inline]
    226    pub fn multiply(&self, other: &Self) -> Self {
    227        Matrix3D {
    228            m11: self.m11 * other.m11 + self.m12 * other.m21 +
    229                 self.m13 * other.m31 + self.m14 * other.m41,
    230            m12: self.m11 * other.m12 + self.m12 * other.m22 +
    231                 self.m13 * other.m32 + self.m14 * other.m42,
    232            m13: self.m11 * other.m13 + self.m12 * other.m23 +
    233                 self.m13 * other.m33 + self.m14 * other.m43,
    234            m14: self.m11 * other.m14 + self.m12 * other.m24 +
    235                 self.m13 * other.m34 + self.m14 * other.m44,
    236            m21: self.m21 * other.m11 + self.m22 * other.m21 +
    237                 self.m23 * other.m31 + self.m24 * other.m41,
    238            m22: self.m21 * other.m12 + self.m22 * other.m22 +
    239                 self.m23 * other.m32 + self.m24 * other.m42,
    240            m23: self.m21 * other.m13 + self.m22 * other.m23 +
    241                 self.m23 * other.m33 + self.m24 * other.m43,
    242            m24: self.m21 * other.m14 + self.m22 * other.m24 +
    243                 self.m23 * other.m34 + self.m24 * other.m44,
    244            m31: self.m31 * other.m11 + self.m32 * other.m21 +
    245                 self.m33 * other.m31 + self.m34 * other.m41,
    246            m32: self.m31 * other.m12 + self.m32 * other.m22 +
    247                 self.m33 * other.m32 + self.m34 * other.m42,
    248            m33: self.m31 * other.m13 + self.m32 * other.m23 +
    249                 self.m33 * other.m33 + self.m34 * other.m43,
    250            m34: self.m31 * other.m14 + self.m32 * other.m24 +
    251                 self.m33 * other.m34 + self.m34 * other.m44,
    252            m41: self.m41 * other.m11 + self.m42 * other.m21 +
    253                 self.m43 * other.m31 + self.m44 * other.m41,
    254            m42: self.m41 * other.m12 + self.m42 * other.m22 +
    255                 self.m43 * other.m32 + self.m44 * other.m42,
    256            m43: self.m41 * other.m13 + self.m42 * other.m23 +
    257                 self.m43 * other.m33 + self.m44 * other.m43,
    258            m44: self.m41 * other.m14 + self.m42 * other.m24 +
    259                 self.m43 * other.m34 + self.m44 * other.m44,
    260        }
    261    }
    262 
    263    /// Scale the matrix by a factor.
    264    #[inline]
    265    pub fn scale_by_factor(&mut self, scaling_factor: CSSFloat) {
    266        self.m11 *= scaling_factor;
    267        self.m12 *= scaling_factor;
    268        self.m13 *= scaling_factor;
    269        self.m14 *= scaling_factor;
    270        self.m21 *= scaling_factor;
    271        self.m22 *= scaling_factor;
    272        self.m23 *= scaling_factor;
    273        self.m24 *= scaling_factor;
    274        self.m31 *= scaling_factor;
    275        self.m32 *= scaling_factor;
    276        self.m33 *= scaling_factor;
    277        self.m34 *= scaling_factor;
    278        self.m41 *= scaling_factor;
    279        self.m42 *= scaling_factor;
    280        self.m43 *= scaling_factor;
    281        self.m44 *= scaling_factor;
    282    }
    283 
    284    /// Return the matrix 3x3 part (top-left corner).
    285    /// This is used by retrieving the scale and shear factors
    286    /// during decomposing a 3d matrix.
    287    #[inline]
    288    pub fn get_matrix_3x3_part(&self) -> [[f32; 3]; 3] {
    289        [
    290            [ self.m11, self.m12, self.m13 ],
    291            [ self.m21, self.m22, self.m23 ],
    292            [ self.m31, self.m32, self.m33 ],
    293        ]
    294    }
    295 
    296    /// Set perspective on the matrix.
    297    #[inline]
    298    pub fn set_perspective(&mut self, perspective: &Perspective) {
    299        self.m14 = perspective.0;
    300        self.m24 = perspective.1;
    301        self.m34 = perspective.2;
    302        self.m44 = perspective.3;
    303    }
    304 
    305    /// Apply translate on the matrix.
    306    #[inline]
    307    pub fn apply_translate(&mut self, translate: &Translate3D) {
    308        self.m41 += translate.0 * self.m11 + translate.1 * self.m21 + translate.2 * self.m31;
    309        self.m42 += translate.0 * self.m12 + translate.1 * self.m22 + translate.2 * self.m32;
    310        self.m43 += translate.0 * self.m13 + translate.1 * self.m23 + translate.2 * self.m33;
    311        self.m44 += translate.0 * self.m14 + translate.1 * self.m24 + translate.2 * self.m34;
    312    }
    313 
    314    /// Apply scale on the matrix.
    315    #[inline]
    316    pub fn apply_scale(&mut self, scale: &Scale3D) {
    317        self.m11 *= scale.0;
    318        self.m12 *= scale.0;
    319        self.m13 *= scale.0;
    320        self.m14 *= scale.0;
    321        self.m21 *= scale.1;
    322        self.m22 *= scale.1;
    323        self.m23 *= scale.1;
    324        self.m24 *= scale.1;
    325        self.m31 *= scale.2;
    326        self.m32 *= scale.2;
    327        self.m33 *= scale.2;
    328        self.m34 *= scale.2;
    329    }
    330 }
    331 
    332 #[cfg_attr(rustfmt, rustfmt_skip)]
    333 impl Matrix {
    334    #[inline]
    335    /// Get an identity matrix
    336    pub fn identity() -> Self {
    337        Self {
    338            a: 1., c: 0., /* 0      0*/
    339            b: 0., d: 1., /* 0      0*/
    340            /* 0      0      1      0 */
    341            e: 0., f: 0., /* 0      1 */
    342        }
    343    }
    344 }
    345 
    346 #[cfg_attr(rustfmt, rustfmt_skip)]
    347 impl From<Matrix> for Matrix3D {
    348    fn from(m: Matrix) -> Self {
    349        Self {
    350            m11: m.a, m12: m.b, m13: 0.0, m14: 0.0,
    351            m21: m.c, m22: m.d, m23: 0.0, m24: 0.0,
    352            m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
    353            m41: m.e, m42: m.f, m43: 0.0, m44: 1.0
    354        }
    355    }
    356 }
    357 
    358 #[cfg_attr(rustfmt, rustfmt_skip)]
    359 impl From<Transform3D<CSSFloat>> for Matrix3D {
    360    #[inline]
    361    fn from(m: Transform3D<CSSFloat>) -> Self {
    362        Matrix3D {
    363            m11: m.m11, m12: m.m12, m13: m.m13, m14: m.m14,
    364            m21: m.m21, m22: m.m22, m23: m.m23, m24: m.m24,
    365            m31: m.m31, m32: m.m32, m33: m.m33, m34: m.m34,
    366            m41: m.m41, m42: m.m42, m43: m.m43, m44: m.m44
    367        }
    368    }
    369 }
    370 
    371 impl TransformOperation {
    372    /// Convert to a Translate3D.
    373    ///
    374    /// Must be called on a Translate function
    375    pub fn to_translate_3d(&self) -> Self {
    376        match *self {
    377            generic::TransformOperation::Translate3D(..) => self.clone(),
    378            generic::TransformOperation::TranslateX(ref x) => {
    379                generic::TransformOperation::Translate3D(
    380                    x.clone(),
    381                    LengthPercentage::zero(),
    382                    Length::zero(),
    383                )
    384            },
    385            generic::TransformOperation::Translate(ref x, ref y) => {
    386                generic::TransformOperation::Translate3D(x.clone(), y.clone(), Length::zero())
    387            },
    388            generic::TransformOperation::TranslateY(ref y) => {
    389                generic::TransformOperation::Translate3D(
    390                    LengthPercentage::zero(),
    391                    y.clone(),
    392                    Length::zero(),
    393                )
    394            },
    395            generic::TransformOperation::TranslateZ(ref z) => {
    396                generic::TransformOperation::Translate3D(
    397                    LengthPercentage::zero(),
    398                    LengthPercentage::zero(),
    399                    z.clone(),
    400                )
    401            },
    402            _ => unreachable!(),
    403        }
    404    }
    405 
    406    /// Convert to a Rotate3D.
    407    ///
    408    /// Must be called on a Rotate function.
    409    pub fn to_rotate_3d(&self) -> Self {
    410        match *self {
    411            generic::TransformOperation::Rotate3D(..) => self.clone(),
    412            generic::TransformOperation::RotateZ(ref angle)
    413            | generic::TransformOperation::Rotate(ref angle) => {
    414                generic::TransformOperation::Rotate3D(0., 0., 1., angle.clone())
    415            },
    416            generic::TransformOperation::RotateX(ref angle) => {
    417                generic::TransformOperation::Rotate3D(1., 0., 0., angle.clone())
    418            },
    419            generic::TransformOperation::RotateY(ref angle) => {
    420                generic::TransformOperation::Rotate3D(0., 1., 0., angle.clone())
    421            },
    422            _ => unreachable!(),
    423        }
    424    }
    425 
    426    /// Convert to a Scale3D.
    427    ///
    428    /// Must be called on a Scale function
    429    pub fn to_scale_3d(&self) -> Self {
    430        match *self {
    431            generic::TransformOperation::Scale3D(..) => self.clone(),
    432            generic::TransformOperation::Scale(x, y) => {
    433                generic::TransformOperation::Scale3D(x, y, 1.)
    434            },
    435            generic::TransformOperation::ScaleX(x) => {
    436                generic::TransformOperation::Scale3D(x, 1., 1.)
    437            },
    438            generic::TransformOperation::ScaleY(y) => {
    439                generic::TransformOperation::Scale3D(1., y, 1.)
    440            },
    441            generic::TransformOperation::ScaleZ(z) => {
    442                generic::TransformOperation::Scale3D(1., 1., z)
    443            },
    444            _ => unreachable!(),
    445        }
    446    }
    447 }
    448 
    449 /// Build an equivalent 'identity transform function list' based
    450 /// on an existing transform list.
    451 /// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
    452 impl ToAnimatedZero for TransformOperation {
    453    fn to_animated_zero(&self) -> Result<Self, ()> {
    454        match *self {
    455            generic::TransformOperation::Matrix3D(..) => {
    456                Ok(generic::TransformOperation::Matrix3D(Matrix3D::identity()))
    457            },
    458            generic::TransformOperation::Matrix(..) => {
    459                Ok(generic::TransformOperation::Matrix(Matrix::identity()))
    460            },
    461            generic::TransformOperation::Skew(sx, sy) => Ok(generic::TransformOperation::Skew(
    462                sx.to_animated_zero()?,
    463                sy.to_animated_zero()?,
    464            )),
    465            generic::TransformOperation::SkewX(s) => {
    466                Ok(generic::TransformOperation::SkewX(s.to_animated_zero()?))
    467            },
    468            generic::TransformOperation::SkewY(s) => {
    469                Ok(generic::TransformOperation::SkewY(s.to_animated_zero()?))
    470            },
    471            generic::TransformOperation::Translate3D(ref tx, ref ty, ref tz) => {
    472                Ok(generic::TransformOperation::Translate3D(
    473                    tx.to_animated_zero()?,
    474                    ty.to_animated_zero()?,
    475                    tz.to_animated_zero()?,
    476                ))
    477            },
    478            generic::TransformOperation::Translate(ref tx, ref ty) => {
    479                Ok(generic::TransformOperation::Translate(
    480                    tx.to_animated_zero()?,
    481                    ty.to_animated_zero()?,
    482                ))
    483            },
    484            generic::TransformOperation::TranslateX(ref t) => Ok(
    485                generic::TransformOperation::TranslateX(t.to_animated_zero()?),
    486            ),
    487            generic::TransformOperation::TranslateY(ref t) => Ok(
    488                generic::TransformOperation::TranslateY(t.to_animated_zero()?),
    489            ),
    490            generic::TransformOperation::TranslateZ(ref t) => Ok(
    491                generic::TransformOperation::TranslateZ(t.to_animated_zero()?),
    492            ),
    493            generic::TransformOperation::Scale3D(..) => {
    494                Ok(generic::TransformOperation::Scale3D(1.0, 1.0, 1.0))
    495            },
    496            generic::TransformOperation::Scale(_, _) => {
    497                Ok(generic::TransformOperation::Scale(1.0, 1.0))
    498            },
    499            generic::TransformOperation::ScaleX(..) => Ok(generic::TransformOperation::ScaleX(1.0)),
    500            generic::TransformOperation::ScaleY(..) => Ok(generic::TransformOperation::ScaleY(1.0)),
    501            generic::TransformOperation::ScaleZ(..) => Ok(generic::TransformOperation::ScaleZ(1.0)),
    502            generic::TransformOperation::Rotate3D(x, y, z, a) => {
    503                let (x, y, z, _) = generic::get_normalized_vector_and_angle(x, y, z, a);
    504                Ok(generic::TransformOperation::Rotate3D(
    505                    x,
    506                    y,
    507                    z,
    508                    Angle::zero(),
    509                ))
    510            },
    511            generic::TransformOperation::RotateX(_) => {
    512                Ok(generic::TransformOperation::RotateX(Angle::zero()))
    513            },
    514            generic::TransformOperation::RotateY(_) => {
    515                Ok(generic::TransformOperation::RotateY(Angle::zero()))
    516            },
    517            generic::TransformOperation::RotateZ(_) => {
    518                Ok(generic::TransformOperation::RotateZ(Angle::zero()))
    519            },
    520            generic::TransformOperation::Rotate(_) => {
    521                Ok(generic::TransformOperation::Rotate(Angle::zero()))
    522            },
    523            generic::TransformOperation::Perspective(_) => Ok(
    524                generic::TransformOperation::Perspective(generic::PerspectiveFunction::None),
    525            ),
    526            generic::TransformOperation::AccumulateMatrix { .. }
    527            | generic::TransformOperation::InterpolateMatrix { .. } => {
    528                // AccumulateMatrix/InterpolateMatrix: We do interpolation on
    529                //     AccumulateMatrix/InterpolateMatrix by reading it as a ComputedMatrix
    530                //     (with layout information), and then do matrix interpolation.
    531                //
    532                // Therefore, we use an identity matrix to represent the identity transform list.
    533                // http://dev.w3.org/csswg/css-transforms/#identity-transform-function
    534                Ok(generic::TransformOperation::Matrix3D(Matrix3D::identity()))
    535            },
    536        }
    537    }
    538 }
    539 
    540 impl ToAnimatedZero for Transform {
    541    #[inline]
    542    fn to_animated_zero(&self) -> Result<Self, ()> {
    543        Ok(generic::Transform(
    544            self.0
    545                .iter()
    546                .map(|op| op.to_animated_zero())
    547                .collect::<Result<crate::OwnedSlice<_>, _>>()?,
    548        ))
    549    }
    550 }
    551 
    552 /// A computed CSS `rotate`
    553 pub type Rotate = generic::GenericRotate<Number, Angle>;
    554 
    555 /// A computed CSS `translate`
    556 pub type Translate = generic::GenericTranslate<LengthPercentage, Length>;
    557 
    558 /// A computed CSS `scale`
    559 pub type Scale = generic::GenericScale<Number>;