mirror of
https://github.com/servo/servo
synced 2026-05-09 08:32:31 +02:00
This may or may not be part of the plan to get rid of nsCSSValue ;) Option is not usable via FFI, and they should not be needed (we should be following the shortest serialization principle instead). These patches also do that, which matches the other transform properties. I think that slight change is fine, if we can make it work, and consistent with other properties. Alternative is adding more TransformOperation variants or such, which I rather not do. Differential Revision: https://phabricator.services.mozilla.com/D21862
630 lines
26 KiB
Rust
630 lines
26 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
//! Computed types for CSS values that are related to transformations.
|
|
|
|
use super::CSSFloat;
|
|
use crate::values::animated::transform::{Perspective, Scale3D, Translate3D};
|
|
use crate::values::animated::ToAnimatedZero;
|
|
use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
|
|
use crate::values::generics::transform as generic;
|
|
use crate::Zero;
|
|
use euclid::{Transform3D, Vector3D};
|
|
|
|
pub use crate::values::generics::transform::TransformStyle;
|
|
|
|
/// A single operation in a computed CSS `transform`
|
|
pub type TransformOperation =
|
|
generic::TransformOperation<Angle, Number, Length, Integer, LengthPercentage>;
|
|
/// A computed CSS `transform`
|
|
pub type Transform = generic::Transform<TransformOperation>;
|
|
|
|
/// The computed value of a CSS `<transform-origin>`
|
|
pub type TransformOrigin =
|
|
generic::GenericTransformOrigin<LengthPercentage, LengthPercentage, Length>;
|
|
|
|
/// A vector to represent the direction vector (rotate axis) for Rotate3D.
|
|
pub type DirectionVector = Vector3D<CSSFloat>;
|
|
|
|
impl TransformOrigin {
|
|
/// Returns the initial computed value for `transform-origin`.
|
|
#[inline]
|
|
pub fn initial_value() -> Self {
|
|
Self::new(
|
|
LengthPercentage::new_percent(Percentage(0.5)),
|
|
LengthPercentage::new_percent(Percentage(0.5)),
|
|
Length::new(0.),
|
|
)
|
|
}
|
|
}
|
|
|
|
/// computed value of matrix3d()
|
|
pub type Matrix3D = generic::Matrix3D<Number>;
|
|
|
|
/// computed value of matrix()
|
|
pub type Matrix = generic::Matrix<Number>;
|
|
|
|
// we rustfmt_skip here because we want the matrices to look like
|
|
// matrices instead of being split across lines
|
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
impl Matrix3D {
|
|
/// Get an identity matrix
|
|
#[inline]
|
|
pub fn identity() -> Self {
|
|
Self {
|
|
m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
|
|
m21: 0.0, m22: 1.0, m23: 0.0, m24: 0.0,
|
|
m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
|
|
m41: 0., m42: 0., m43: 0., m44: 1.0
|
|
}
|
|
}
|
|
|
|
/// Convert to a 2D Matrix
|
|
#[inline]
|
|
pub fn into_2d(self) -> Result<Matrix, ()> {
|
|
if self.m13 == 0. && self.m23 == 0. &&
|
|
self.m31 == 0. && self.m32 == 0. &&
|
|
self.m33 == 1. && self.m34 == 0. &&
|
|
self.m14 == 0. && self.m24 == 0. &&
|
|
self.m43 == 0. && self.m44 == 1. {
|
|
Ok(Matrix {
|
|
a: self.m11, c: self.m21, e: self.m41,
|
|
b: self.m12, d: self.m22, f: self.m42,
|
|
})
|
|
} else {
|
|
Err(())
|
|
}
|
|
}
|
|
|
|
/// Return true if this has 3D components.
|
|
#[inline]
|
|
pub fn is_3d(&self) -> bool {
|
|
self.m13 != 0.0 || self.m14 != 0.0 ||
|
|
self.m23 != 0.0 || self.m24 != 0.0 ||
|
|
self.m31 != 0.0 || self.m32 != 0.0 ||
|
|
self.m33 != 1.0 || self.m34 != 0.0 ||
|
|
self.m43 != 0.0 || self.m44 != 1.0
|
|
}
|
|
|
|
/// Return determinant value.
|
|
#[inline]
|
|
pub fn determinant(&self) -> CSSFloat {
|
|
self.m14 * self.m23 * self.m32 * self.m41 -
|
|
self.m13 * self.m24 * self.m32 * self.m41 -
|
|
self.m14 * self.m22 * self.m33 * self.m41 +
|
|
self.m12 * self.m24 * self.m33 * self.m41 +
|
|
self.m13 * self.m22 * self.m34 * self.m41 -
|
|
self.m12 * self.m23 * self.m34 * self.m41 -
|
|
self.m14 * self.m23 * self.m31 * self.m42 +
|
|
self.m13 * self.m24 * self.m31 * self.m42 +
|
|
self.m14 * self.m21 * self.m33 * self.m42 -
|
|
self.m11 * self.m24 * self.m33 * self.m42 -
|
|
self.m13 * self.m21 * self.m34 * self.m42 +
|
|
self.m11 * self.m23 * self.m34 * self.m42 +
|
|
self.m14 * self.m22 * self.m31 * self.m43 -
|
|
self.m12 * self.m24 * self.m31 * self.m43 -
|
|
self.m14 * self.m21 * self.m32 * self.m43 +
|
|
self.m11 * self.m24 * self.m32 * self.m43 +
|
|
self.m12 * self.m21 * self.m34 * self.m43 -
|
|
self.m11 * self.m22 * self.m34 * self.m43 -
|
|
self.m13 * self.m22 * self.m31 * self.m44 +
|
|
self.m12 * self.m23 * self.m31 * self.m44 +
|
|
self.m13 * self.m21 * self.m32 * self.m44 -
|
|
self.m11 * self.m23 * self.m32 * self.m44 -
|
|
self.m12 * self.m21 * self.m33 * self.m44 +
|
|
self.m11 * self.m22 * self.m33 * self.m44
|
|
}
|
|
|
|
/// Transpose a matrix.
|
|
#[inline]
|
|
pub fn transpose(&self) -> Self {
|
|
Self {
|
|
m11: self.m11, m12: self.m21, m13: self.m31, m14: self.m41,
|
|
m21: self.m12, m22: self.m22, m23: self.m32, m24: self.m42,
|
|
m31: self.m13, m32: self.m23, m33: self.m33, m34: self.m43,
|
|
m41: self.m14, m42: self.m24, m43: self.m34, m44: self.m44,
|
|
}
|
|
}
|
|
|
|
/// Return inverse matrix.
|
|
pub fn inverse(&self) -> Result<Matrix3D, ()> {
|
|
let mut det = self.determinant();
|
|
|
|
if det == 0.0 {
|
|
return Err(());
|
|
}
|
|
|
|
det = 1.0 / det;
|
|
let x = Matrix3D {
|
|
m11: det *
|
|
(self.m23 * self.m34 * self.m42 - self.m24 * self.m33 * self.m42 +
|
|
self.m24 * self.m32 * self.m43 - self.m22 * self.m34 * self.m43 -
|
|
self.m23 * self.m32 * self.m44 + self.m22 * self.m33 * self.m44),
|
|
m12: det *
|
|
(self.m14 * self.m33 * self.m42 - self.m13 * self.m34 * self.m42 -
|
|
self.m14 * self.m32 * self.m43 + self.m12 * self.m34 * self.m43 +
|
|
self.m13 * self.m32 * self.m44 - self.m12 * self.m33 * self.m44),
|
|
m13: det *
|
|
(self.m13 * self.m24 * self.m42 - self.m14 * self.m23 * self.m42 +
|
|
self.m14 * self.m22 * self.m43 - self.m12 * self.m24 * self.m43 -
|
|
self.m13 * self.m22 * self.m44 + self.m12 * self.m23 * self.m44),
|
|
m14: det *
|
|
(self.m14 * self.m23 * self.m32 - self.m13 * self.m24 * self.m32 -
|
|
self.m14 * self.m22 * self.m33 + self.m12 * self.m24 * self.m33 +
|
|
self.m13 * self.m22 * self.m34 - self.m12 * self.m23 * self.m34),
|
|
m21: det *
|
|
(self.m24 * self.m33 * self.m41 - self.m23 * self.m34 * self.m41 -
|
|
self.m24 * self.m31 * self.m43 + self.m21 * self.m34 * self.m43 +
|
|
self.m23 * self.m31 * self.m44 - self.m21 * self.m33 * self.m44),
|
|
m22: det *
|
|
(self.m13 * self.m34 * self.m41 - self.m14 * self.m33 * self.m41 +
|
|
self.m14 * self.m31 * self.m43 - self.m11 * self.m34 * self.m43 -
|
|
self.m13 * self.m31 * self.m44 + self.m11 * self.m33 * self.m44),
|
|
m23: det *
|
|
(self.m14 * self.m23 * self.m41 - self.m13 * self.m24 * self.m41 -
|
|
self.m14 * self.m21 * self.m43 + self.m11 * self.m24 * self.m43 +
|
|
self.m13 * self.m21 * self.m44 - self.m11 * self.m23 * self.m44),
|
|
m24: det *
|
|
(self.m13 * self.m24 * self.m31 - self.m14 * self.m23 * self.m31 +
|
|
self.m14 * self.m21 * self.m33 - self.m11 * self.m24 * self.m33 -
|
|
self.m13 * self.m21 * self.m34 + self.m11 * self.m23 * self.m34),
|
|
m31: det *
|
|
(self.m22 * self.m34 * self.m41 - self.m24 * self.m32 * self.m41 +
|
|
self.m24 * self.m31 * self.m42 - self.m21 * self.m34 * self.m42 -
|
|
self.m22 * self.m31 * self.m44 + self.m21 * self.m32 * self.m44),
|
|
m32: det *
|
|
(self.m14 * self.m32 * self.m41 - self.m12 * self.m34 * self.m41 -
|
|
self.m14 * self.m31 * self.m42 + self.m11 * self.m34 * self.m42 +
|
|
self.m12 * self.m31 * self.m44 - self.m11 * self.m32 * self.m44),
|
|
m33: det *
|
|
(self.m12 * self.m24 * self.m41 - self.m14 * self.m22 * self.m41 +
|
|
self.m14 * self.m21 * self.m42 - self.m11 * self.m24 * self.m42 -
|
|
self.m12 * self.m21 * self.m44 + self.m11 * self.m22 * self.m44),
|
|
m34: det *
|
|
(self.m14 * self.m22 * self.m31 - self.m12 * self.m24 * self.m31 -
|
|
self.m14 * self.m21 * self.m32 + self.m11 * self.m24 * self.m32 +
|
|
self.m12 * self.m21 * self.m34 - self.m11 * self.m22 * self.m34),
|
|
m41: det *
|
|
(self.m23 * self.m32 * self.m41 - self.m22 * self.m33 * self.m41 -
|
|
self.m23 * self.m31 * self.m42 + self.m21 * self.m33 * self.m42 +
|
|
self.m22 * self.m31 * self.m43 - self.m21 * self.m32 * self.m43),
|
|
m42: det *
|
|
(self.m12 * self.m33 * self.m41 - self.m13 * self.m32 * self.m41 +
|
|
self.m13 * self.m31 * self.m42 - self.m11 * self.m33 * self.m42 -
|
|
self.m12 * self.m31 * self.m43 + self.m11 * self.m32 * self.m43),
|
|
m43: det *
|
|
(self.m13 * self.m22 * self.m41 - self.m12 * self.m23 * self.m41 -
|
|
self.m13 * self.m21 * self.m42 + self.m11 * self.m23 * self.m42 +
|
|
self.m12 * self.m21 * self.m43 - self.m11 * self.m22 * self.m43),
|
|
m44: det *
|
|
(self.m12 * self.m23 * self.m31 - self.m13 * self.m22 * self.m31 +
|
|
self.m13 * self.m21 * self.m32 - self.m11 * self.m23 * self.m32 -
|
|
self.m12 * self.m21 * self.m33 + self.m11 * self.m22 * self.m33),
|
|
};
|
|
|
|
Ok(x)
|
|
}
|
|
|
|
/// Multiply `pin * self`.
|
|
#[inline]
|
|
pub fn pre_mul_point4(&self, pin: &[f32; 4]) -> [f32; 4] {
|
|
[
|
|
pin[0] * self.m11 + pin[1] * self.m21 + pin[2] * self.m31 + pin[3] * self.m41,
|
|
pin[0] * self.m12 + pin[1] * self.m22 + pin[2] * self.m32 + pin[3] * self.m42,
|
|
pin[0] * self.m13 + pin[1] * self.m23 + pin[2] * self.m33 + pin[3] * self.m43,
|
|
pin[0] * self.m14 + pin[1] * self.m24 + pin[2] * self.m34 + pin[3] * self.m44,
|
|
]
|
|
}
|
|
|
|
/// Return the multiplication of two 4x4 matrices.
|
|
#[inline]
|
|
pub fn multiply(&self, other: &Self) -> Self {
|
|
Matrix3D {
|
|
m11: self.m11 * other.m11 + self.m12 * other.m21 +
|
|
self.m13 * other.m31 + self.m14 * other.m41,
|
|
m12: self.m11 * other.m12 + self.m12 * other.m22 +
|
|
self.m13 * other.m32 + self.m14 * other.m42,
|
|
m13: self.m11 * other.m13 + self.m12 * other.m23 +
|
|
self.m13 * other.m33 + self.m14 * other.m43,
|
|
m14: self.m11 * other.m14 + self.m12 * other.m24 +
|
|
self.m13 * other.m34 + self.m14 * other.m44,
|
|
m21: self.m21 * other.m11 + self.m22 * other.m21 +
|
|
self.m23 * other.m31 + self.m24 * other.m41,
|
|
m22: self.m21 * other.m12 + self.m22 * other.m22 +
|
|
self.m23 * other.m32 + self.m24 * other.m42,
|
|
m23: self.m21 * other.m13 + self.m22 * other.m23 +
|
|
self.m23 * other.m33 + self.m24 * other.m43,
|
|
m24: self.m21 * other.m14 + self.m22 * other.m24 +
|
|
self.m23 * other.m34 + self.m24 * other.m44,
|
|
m31: self.m31 * other.m11 + self.m32 * other.m21 +
|
|
self.m33 * other.m31 + self.m34 * other.m41,
|
|
m32: self.m31 * other.m12 + self.m32 * other.m22 +
|
|
self.m33 * other.m32 + self.m34 * other.m42,
|
|
m33: self.m31 * other.m13 + self.m32 * other.m23 +
|
|
self.m33 * other.m33 + self.m34 * other.m43,
|
|
m34: self.m31 * other.m14 + self.m32 * other.m24 +
|
|
self.m33 * other.m34 + self.m34 * other.m44,
|
|
m41: self.m41 * other.m11 + self.m42 * other.m21 +
|
|
self.m43 * other.m31 + self.m44 * other.m41,
|
|
m42: self.m41 * other.m12 + self.m42 * other.m22 +
|
|
self.m43 * other.m32 + self.m44 * other.m42,
|
|
m43: self.m41 * other.m13 + self.m42 * other.m23 +
|
|
self.m43 * other.m33 + self.m44 * other.m43,
|
|
m44: self.m41 * other.m14 + self.m42 * other.m24 +
|
|
self.m43 * other.m34 + self.m44 * other.m44,
|
|
}
|
|
}
|
|
|
|
/// Scale the matrix by a factor.
|
|
#[inline]
|
|
pub fn scale_by_factor(&mut self, scaling_factor: CSSFloat) {
|
|
self.m11 *= scaling_factor;
|
|
self.m12 *= scaling_factor;
|
|
self.m13 *= scaling_factor;
|
|
self.m14 *= scaling_factor;
|
|
self.m21 *= scaling_factor;
|
|
self.m22 *= scaling_factor;
|
|
self.m23 *= scaling_factor;
|
|
self.m24 *= scaling_factor;
|
|
self.m31 *= scaling_factor;
|
|
self.m32 *= scaling_factor;
|
|
self.m33 *= scaling_factor;
|
|
self.m34 *= scaling_factor;
|
|
self.m41 *= scaling_factor;
|
|
self.m42 *= scaling_factor;
|
|
self.m43 *= scaling_factor;
|
|
self.m44 *= scaling_factor;
|
|
}
|
|
|
|
/// Return the matrix 3x3 part (top-left corner).
|
|
/// This is used by retrieving the scale and shear factors
|
|
/// during decomposing a 3d matrix.
|
|
#[inline]
|
|
pub fn get_matrix_3x3_part(&self) -> [[f32; 3]; 3] {
|
|
[
|
|
[ self.m11, self.m12, self.m13 ],
|
|
[ self.m21, self.m22, self.m23 ],
|
|
[ self.m31, self.m32, self.m33 ],
|
|
]
|
|
}
|
|
|
|
/// Set perspective on the matrix.
|
|
#[inline]
|
|
pub fn set_perspective(&mut self, perspective: &Perspective) {
|
|
self.m14 = perspective.0;
|
|
self.m24 = perspective.1;
|
|
self.m34 = perspective.2;
|
|
self.m44 = perspective.3;
|
|
}
|
|
|
|
/// Apply translate on the matrix.
|
|
#[inline]
|
|
pub fn apply_translate(&mut self, translate: &Translate3D) {
|
|
self.m41 += translate.0 * self.m11 + translate.1 * self.m21 + translate.2 * self.m31;
|
|
self.m42 += translate.0 * self.m12 + translate.1 * self.m22 + translate.2 * self.m32;
|
|
self.m43 += translate.0 * self.m13 + translate.1 * self.m23 + translate.2 * self.m33;
|
|
self.m44 += translate.0 * self.m14 + translate.1 * self.m24 + translate.2 * self.m34;
|
|
}
|
|
|
|
/// Apply scale on the matrix.
|
|
#[inline]
|
|
pub fn apply_scale(&mut self, scale: &Scale3D) {
|
|
self.m11 *= scale.0;
|
|
self.m12 *= scale.0;
|
|
self.m13 *= scale.0;
|
|
self.m14 *= scale.0;
|
|
self.m21 *= scale.1;
|
|
self.m22 *= scale.1;
|
|
self.m23 *= scale.1;
|
|
self.m24 *= scale.1;
|
|
self.m31 *= scale.2;
|
|
self.m32 *= scale.2;
|
|
self.m33 *= scale.2;
|
|
self.m34 *= scale.2;
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
impl Matrix {
|
|
#[inline]
|
|
/// Get an identity matrix
|
|
pub fn identity() -> Self {
|
|
Self {
|
|
a: 1., c: 0., /* 0 0*/
|
|
b: 0., d: 1., /* 0 0*/
|
|
/* 0 0 1 0 */
|
|
e: 0., f: 0., /* 0 1 */
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
impl From<Matrix> for Matrix3D {
|
|
fn from(m: Matrix) -> Self {
|
|
Self {
|
|
m11: m.a, m12: m.b, m13: 0.0, m14: 0.0,
|
|
m21: m.c, m22: m.d, m23: 0.0, m24: 0.0,
|
|
m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
|
|
m41: m.e, m42: m.f, m43: 0.0, m44: 1.0
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
impl From<Transform3D<CSSFloat>> for Matrix3D {
|
|
#[inline]
|
|
fn from(m: Transform3D<CSSFloat>) -> Self {
|
|
Matrix3D {
|
|
m11: m.m11, m12: m.m12, m13: m.m13, m14: m.m14,
|
|
m21: m.m21, m22: m.m22, m23: m.m23, m24: m.m24,
|
|
m31: m.m31, m32: m.m32, m33: m.m33, m34: m.m34,
|
|
m41: m.m41, m42: m.m42, m43: m.m43, m44: m.m44
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TransformOperation {
|
|
/// Convert to a Translate3D.
|
|
///
|
|
/// Must be called on a Translate function
|
|
pub fn to_translate_3d(&self) -> Self {
|
|
match *self {
|
|
generic::TransformOperation::Translate3D(..) => self.clone(),
|
|
generic::TransformOperation::TranslateX(ref x) => {
|
|
generic::TransformOperation::Translate3D(
|
|
x.clone(),
|
|
LengthPercentage::zero(),
|
|
Length::zero(),
|
|
)
|
|
},
|
|
generic::TransformOperation::Translate(ref x, ref y) => {
|
|
generic::TransformOperation::Translate3D(x.clone(), y.clone(), Length::zero())
|
|
},
|
|
generic::TransformOperation::TranslateY(ref y) => {
|
|
generic::TransformOperation::Translate3D(
|
|
LengthPercentage::zero(),
|
|
y.clone(),
|
|
Length::zero(),
|
|
)
|
|
},
|
|
generic::TransformOperation::TranslateZ(ref z) => {
|
|
generic::TransformOperation::Translate3D(
|
|
LengthPercentage::zero(),
|
|
LengthPercentage::zero(),
|
|
z.clone(),
|
|
)
|
|
},
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
/// Convert to a Rotate3D.
|
|
///
|
|
/// Must be called on a Rotate function.
|
|
pub fn to_rotate_3d(&self) -> Self {
|
|
match *self {
|
|
generic::TransformOperation::Rotate3D(..) => self.clone(),
|
|
generic::TransformOperation::RotateZ(ref angle) |
|
|
generic::TransformOperation::Rotate(ref angle) => {
|
|
generic::TransformOperation::Rotate3D(0., 0., 1., angle.clone())
|
|
},
|
|
generic::TransformOperation::RotateX(ref angle) => {
|
|
generic::TransformOperation::Rotate3D(1., 0., 0., angle.clone())
|
|
},
|
|
generic::TransformOperation::RotateY(ref angle) => {
|
|
generic::TransformOperation::Rotate3D(0., 1., 0., angle.clone())
|
|
},
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
/// Convert to a Scale3D.
|
|
///
|
|
/// Must be called on a Scale function
|
|
pub fn to_scale_3d(&self) -> Self {
|
|
match *self {
|
|
generic::TransformOperation::Scale3D(..) => self.clone(),
|
|
generic::TransformOperation::Scale(x, y) => {
|
|
generic::TransformOperation::Scale3D(x, y, 1.)
|
|
},
|
|
generic::TransformOperation::ScaleX(x) => {
|
|
generic::TransformOperation::Scale3D(x, 1., 1.)
|
|
},
|
|
generic::TransformOperation::ScaleY(y) => {
|
|
generic::TransformOperation::Scale3D(1., y, 1.)
|
|
},
|
|
generic::TransformOperation::ScaleZ(z) => {
|
|
generic::TransformOperation::Scale3D(1., 1., z)
|
|
},
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Build an equivalent 'identity transform function list' based
|
|
/// on an existing transform list.
|
|
/// http://dev.w3.org/csswg/css-transforms/#none-transform-animation
|
|
impl ToAnimatedZero for TransformOperation {
|
|
fn to_animated_zero(&self) -> Result<Self, ()> {
|
|
match *self {
|
|
generic::TransformOperation::Matrix3D(..) => {
|
|
Ok(generic::TransformOperation::Matrix3D(Matrix3D::identity()))
|
|
},
|
|
generic::TransformOperation::Matrix(..) => {
|
|
Ok(generic::TransformOperation::Matrix(Matrix::identity()))
|
|
},
|
|
generic::TransformOperation::Skew(sx, sy) => Ok(generic::TransformOperation::Skew(
|
|
sx.to_animated_zero()?,
|
|
sy.to_animated_zero()?,
|
|
)),
|
|
generic::TransformOperation::SkewX(s) => {
|
|
Ok(generic::TransformOperation::SkewX(s.to_animated_zero()?))
|
|
},
|
|
generic::TransformOperation::SkewY(s) => {
|
|
Ok(generic::TransformOperation::SkewY(s.to_animated_zero()?))
|
|
},
|
|
generic::TransformOperation::Translate3D(ref tx, ref ty, ref tz) => {
|
|
Ok(generic::TransformOperation::Translate3D(
|
|
tx.to_animated_zero()?,
|
|
ty.to_animated_zero()?,
|
|
tz.to_animated_zero()?,
|
|
))
|
|
},
|
|
generic::TransformOperation::Translate(ref tx, ref ty) => {
|
|
Ok(generic::TransformOperation::Translate(
|
|
tx.to_animated_zero()?,
|
|
ty.to_animated_zero()?,
|
|
))
|
|
},
|
|
generic::TransformOperation::TranslateX(ref t) => Ok(
|
|
generic::TransformOperation::TranslateX(t.to_animated_zero()?),
|
|
),
|
|
generic::TransformOperation::TranslateY(ref t) => Ok(
|
|
generic::TransformOperation::TranslateY(t.to_animated_zero()?),
|
|
),
|
|
generic::TransformOperation::TranslateZ(ref t) => Ok(
|
|
generic::TransformOperation::TranslateZ(t.to_animated_zero()?),
|
|
),
|
|
generic::TransformOperation::Scale3D(..) => {
|
|
Ok(generic::TransformOperation::Scale3D(1.0, 1.0, 1.0))
|
|
},
|
|
generic::TransformOperation::Scale(_, _) => {
|
|
Ok(generic::TransformOperation::Scale(1.0, 1.0))
|
|
},
|
|
generic::TransformOperation::ScaleX(..) => Ok(generic::TransformOperation::ScaleX(1.0)),
|
|
generic::TransformOperation::ScaleY(..) => Ok(generic::TransformOperation::ScaleY(1.0)),
|
|
generic::TransformOperation::ScaleZ(..) => Ok(generic::TransformOperation::ScaleZ(1.0)),
|
|
generic::TransformOperation::Rotate3D(x, y, z, a) => {
|
|
let (x, y, z, _) = generic::get_normalized_vector_and_angle(x, y, z, a);
|
|
Ok(generic::TransformOperation::Rotate3D(
|
|
x,
|
|
y,
|
|
z,
|
|
Angle::zero(),
|
|
))
|
|
},
|
|
generic::TransformOperation::RotateX(_) => {
|
|
Ok(generic::TransformOperation::RotateX(Angle::zero()))
|
|
},
|
|
generic::TransformOperation::RotateY(_) => {
|
|
Ok(generic::TransformOperation::RotateY(Angle::zero()))
|
|
},
|
|
generic::TransformOperation::RotateZ(_) => {
|
|
Ok(generic::TransformOperation::RotateZ(Angle::zero()))
|
|
},
|
|
generic::TransformOperation::Rotate(_) => {
|
|
Ok(generic::TransformOperation::Rotate(Angle::zero()))
|
|
},
|
|
generic::TransformOperation::Perspective(ref l) => Ok(
|
|
generic::TransformOperation::Perspective(l.to_animated_zero()?),
|
|
),
|
|
generic::TransformOperation::AccumulateMatrix { .. } |
|
|
generic::TransformOperation::InterpolateMatrix { .. } => {
|
|
// AccumulateMatrix/InterpolateMatrix: We do interpolation on
|
|
// AccumulateMatrix/InterpolateMatrix 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
|
|
Ok(generic::TransformOperation::Matrix3D(Matrix3D::identity()))
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ToAnimatedZero for Transform {
|
|
#[inline]
|
|
fn to_animated_zero(&self) -> Result<Self, ()> {
|
|
Ok(generic::Transform(
|
|
self.0
|
|
.iter()
|
|
.map(|op| op.to_animated_zero())
|
|
.collect::<Result<Vec<_>, _>>()?,
|
|
))
|
|
}
|
|
}
|
|
|
|
/// A computed CSS `rotate`
|
|
pub type Rotate = generic::Rotate<Number, Angle>;
|
|
|
|
impl Rotate {
|
|
/// Convert TransformOperation to Rotate.
|
|
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
|
match *self {
|
|
generic::Rotate::None => None,
|
|
generic::Rotate::Rotate(angle) => Some(generic::TransformOperation::Rotate(angle)),
|
|
generic::Rotate::Rotate3D(rx, ry, rz, angle) => {
|
|
Some(generic::TransformOperation::Rotate3D(rx, ry, rz, angle))
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Convert Rotate to TransformOperation.
|
|
pub fn from_transform_operation(operation: &TransformOperation) -> Rotate {
|
|
match *operation {
|
|
generic::TransformOperation::Rotate(angle) => generic::Rotate::Rotate(angle),
|
|
generic::TransformOperation::Rotate3D(rx, ry, rz, angle) => {
|
|
generic::Rotate::Rotate3D(rx, ry, rz, angle)
|
|
},
|
|
_ => unreachable!("Found unexpected value for rotate property"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A computed CSS `translate`
|
|
pub type Translate = generic::Translate<LengthPercentage, Length>;
|
|
|
|
impl Translate {
|
|
/// Convert TransformOperation to Translate.
|
|
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
|
match *self {
|
|
generic::Translate::None => None,
|
|
generic::Translate::Translate(tx, ty) => {
|
|
Some(generic::TransformOperation::Translate(tx, ty))
|
|
},
|
|
generic::Translate::Translate3D(tx, ty, tz) => {
|
|
Some(generic::TransformOperation::Translate3D(tx, ty, tz))
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Convert Translate to TransformOperation.
|
|
pub fn from_transform_operation(operation: &TransformOperation) -> Translate {
|
|
match *operation {
|
|
generic::TransformOperation::Translate(tx, ty) => {
|
|
generic::Translate::Translate(tx, ty)
|
|
},
|
|
generic::TransformOperation::Translate3D(tx, ty, tz) => {
|
|
generic::Translate::Translate3D(tx, ty, tz)
|
|
},
|
|
_ => unreachable!("Found unexpected value for translate"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A computed CSS `scale`
|
|
pub type Scale = generic::Scale<Number>;
|
|
|
|
impl Scale {
|
|
/// Convert TransformOperation to Scale.
|
|
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
|
match *self {
|
|
generic::Scale::None => None,
|
|
generic::Scale::Scale(sx, sy) => Some(generic::TransformOperation::Scale(sx, sy)),
|
|
generic::Scale::Scale3D(sx, sy, sz) => {
|
|
Some(generic::TransformOperation::Scale3D(sx, sy, sz))
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Convert Scale to TransformOperation.
|
|
pub fn from_transform_operation(operation: &TransformOperation) -> Scale {
|
|
match *operation {
|
|
generic::TransformOperation::Scale(sx, sy) => generic::Scale::Scale(sx, sy),
|
|
generic::TransformOperation::Scale3D(sx, sy, sz) => generic::Scale::Scale3D(sx, sy, sz),
|
|
_ => unreachable!("Found unexpected value for scale"),
|
|
}
|
|
}
|
|
}
|