Move decompose and recompose functions to impl and implement interpolations

This commit is contained in:
Nazım Can Altınova 2016-09-07 01:23:00 +03:00
parent 10b631dfd1
commit 5ee93b28cb

View file

@ -21,7 +21,6 @@ use properties::longhands::z_index::computed_value::T as ZIndex;
use std::cmp; use std::cmp;
use std::fmt; use std::fmt;
use super::ComputedValues; use super::ComputedValues;
use values::CSSFloat;
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
use values::computed::{BorderRadiusSize, LengthOrNone}; use values::computed::{BorderRadiusSize, LengthOrNone};
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage}; use values::computed::{CalcLengthOrPercentage, LengthOrPercentage};
@ -624,6 +623,8 @@ impl Interpolate for LengthOrNone {
use properties::longhands::transform::computed_value::ComputedMatrix; use properties::longhands::transform::computed_value::ComputedMatrix;
use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation; use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
use properties::longhands::transform::computed_value::T as TransformList; use properties::longhands::transform::computed_value::T as TransformList;
use values::CSSFloat;
use values::specified::Angle as SpecifiedAngle;
/// Check if it's possible to do a direct numerical interpolation /// Check if it's possible to do a direct numerical interpolation
/// between these two transform lists. /// between these two transform lists.
@ -702,8 +703,9 @@ impl Interpolate for LengthOrNone {
match (from, to) { match (from, to) {
(&TransformOperation::Matrix(from), (&TransformOperation::Matrix(from),
&TransformOperation::Matrix(_to)) => { &TransformOperation::Matrix(_to)) => {
// TODO(gw): Implement matrix decomposition and interpolation // TODO: It doesn't yet handle the case where one of the matrices are not 2D
result.push(TransformOperation::Matrix(from)); let interpolated = from.interpolate(&_to, time).unwrap();
result.push(TransformOperation::Matrix(interpolated));
} }
(&TransformOperation::Skew(fx, fy), (&TransformOperation::Skew(fx, fy),
&TransformOperation::Skew(tx, ty)) => { &TransformOperation::Skew(tx, ty)) => {
@ -735,14 +737,21 @@ impl Interpolate for LengthOrNone {
let ia = fa.interpolate(&ta, time).unwrap(); let ia = fa.interpolate(&ta, time).unwrap();
result.push(TransformOperation::Rotate(fx, fy, fz, ia)); result.push(TransformOperation::Rotate(fx, fy, fz, ia));
} else { } else {
// TODO(gw): Implement matrix decomposition and interpolation let matrix_f = rotate_to_matrix(fx, fy, fz, fa);
result.push(TransformOperation::Rotate(fx, fy, fz, fa)); let matrix_t = rotate_to_matrix(tx, ty, tz, ta);
let interpolated = matrix_f.interpolate(&matrix_t, time).unwrap();
result.push(TransformOperation::Matrix(interpolated));
} }
} }
(&TransformOperation::Perspective(fd), (&TransformOperation::Perspective(fd),
&TransformOperation::Perspective(_td)) => { &TransformOperation::Perspective(_td)) => {
// TODO(gw): Implement matrix decomposition and interpolation let mut fd_matrix = ComputedMatrix::identity();
result.push(TransformOperation::Perspective(fd)); let mut td_matrix = ComputedMatrix::identity();
fd_matrix.m43 = -1. / fd.to_f32_px();
td_matrix.m43 = -1. / _td.to_f32_px();
let interpolated = fd_matrix.interpolate(&td_matrix, time).unwrap();
result.push(TransformOperation::Matrix(interpolated));
} }
_ => { _ => {
// This should be unreachable due to the can_interpolate_list() call. // This should be unreachable due to the can_interpolate_list() call.
@ -758,9 +767,38 @@ impl Interpolate for LengthOrNone {
TransformList(Some(result)) TransformList(Some(result))
} }
/// https://drafts.csswg.org/css-transforms/#Rotate3dDefined
fn rotate_to_matrix(x: f32, y: f32, z: f32, a: SpecifiedAngle) -> ComputedMatrix {
let rad = a.radians();
let sc = (rad / 2.0).sin() * (rad / 2.0).cos();
let sq = 1.0 / 2.0 * (1.0 - (rad).cos());
ComputedMatrix {
m11: 1.0 - 2.0 * (y * y + z * z) * sq,
m12: 2.0 * (x * y * sq - z * sc),
m13: 2.0 * (x * z * sq + y * sc),
m14: 0.0,
m21: 2.0 * (x * y * sq + z * sc),
m22: 1.0 - 2.0 * (x * x + z * z) * sq,
m23: 2.0 * (y * z * sq - x * sc),
m24: 0.0,
m31: 2.0 * (x * z * sq - y * sc),
m32: 2.0 * (y * z * sq + x * sc),
m33: 1.0 - 2.0 * (x * x + y * y) * sq,
m34: 0.0,
m41: 0.0,
m42: 0.0,
m43: 0.0,
m44: 1.0
}
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct DecomposedMatrix { pub struct InnerMatrix2D {
pub m11: CSSFloat, pub m12: CSSFloat, pub m11: CSSFloat, pub m12: CSSFloat,
pub m21: CSSFloat, pub m22: CSSFloat, pub m21: CSSFloat, pub m22: CSSFloat,
} }
@ -779,16 +817,16 @@ impl Interpolate for LengthOrNone {
pub translate: Translate2D, pub translate: Translate2D,
pub scale: Scale2D, pub scale: Scale2D,
pub angle: f32, pub angle: f32,
pub matrix: DecomposedMatrix, pub matrix: InnerMatrix2D,
} }
impl Interpolate for DecomposedMatrix { impl Interpolate for InnerMatrix2D {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(DecomposedMatrix { Ok(InnerMatrix2D {
m11: self.m11.interpolate(&other.m11, time).unwrap(), m11: try!(self.m11.interpolate(&other.m11, time)),
m12: self.m12.interpolate(&other.m12, time).unwrap(), m12: try!(self.m12.interpolate(&other.m12, time)),
m21: self.m21.interpolate(&other.m21, time).unwrap(), m21: try!(self.m21.interpolate(&other.m21, time)),
m22: self.m22.interpolate(&other.m22, time).unwrap(), m22: try!(self.m22.interpolate(&other.m22, time)),
}) })
} }
} }
@ -796,8 +834,8 @@ impl Interpolate for LengthOrNone {
impl Interpolate for Translate2D { impl Interpolate for Translate2D {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(Translate2D( Ok(Translate2D(
self.0.interpolate(&other.0, time).unwrap(), try!(self.0.interpolate(&other.0, time)),
self.1.interpolate(&other.1, time).unwrap() try!(self.1.interpolate(&other.1, time))
)) ))
} }
} }
@ -805,8 +843,8 @@ impl Interpolate for LengthOrNone {
impl Interpolate for Scale2D { impl Interpolate for Scale2D {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(Scale2D( Ok(Scale2D(
self.0.interpolate(&other.0, time).unwrap(), try!(self.0.interpolate(&other.0, time)),
self.1.interpolate(&other.1, time).unwrap() try!(self.1.interpolate(&other.1, time))
)) ))
} }
} }
@ -816,9 +854,9 @@ impl Interpolate for LengthOrNone {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
// If x-axis of one is flipped, and y-axis of the other, // If x-axis of one is flipped, and y-axis of the other,
// convert to an unflipped rotation. // convert to an unflipped rotation.
let mut scale = self.scale.clone(); let mut scale = self.scale;
let mut angle = self.angle.clone(); let mut angle = self.angle;
let mut other_angle = other.angle.clone(); let mut other_angle = other.angle;
if (scale.0 < 0.0 && other.scale.1 < 0.0) || (scale.1 < 0.0 && other.scale.0 < 0.0) { if (scale.0 < 0.0 && other.scale.1 < 0.0) || (scale.1 < 0.0 && other.scale.0 < 0.0) {
scale.0 = -scale.0; scale.0 = -scale.0;
scale.1 = -scale.1; scale.1 = -scale.1;
@ -843,23 +881,33 @@ impl Interpolate for LengthOrNone {
} }
// Interpolate all values. // Interpolate all values.
let translate = self.translate.interpolate(&other.translate, time); let translate = try!(self.translate.interpolate(&other.translate, time));
let scale = scale.interpolate(&other.scale, time); let scale = try!(scale.interpolate(&other.scale, time));
let angle = angle.interpolate(&other_angle, time); let angle = try!(angle.interpolate(&other_angle, time));
let matrix = self.matrix.interpolate(&other.matrix, time); let matrix = try!(self.matrix.interpolate(&other.matrix, time));
Ok(MatrixDecomposed2D { Ok(MatrixDecomposed2D {
translate: translate.unwrap(), translate: translate,
scale: scale.unwrap(), scale: scale,
angle: angle.unwrap(), angle: angle,
matrix: matrix.unwrap(), matrix: matrix,
}) })
} }
} }
impl Interpolate for ComputedMatrix {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
let decomposed_from = MatrixDecomposed2D::from(*self);
let decomposed_to = MatrixDecomposed2D::from(*other);
let interpolated = try!(decomposed_from.interpolate(&decomposed_to, time));
Ok(ComputedMatrix::from(interpolated))
}
}
impl From<ComputedMatrix> for MatrixDecomposed2D {
/// Decompose a matrix. /// Decompose a matrix.
/// https://drafts.csswg.org/css-transforms/#decomposing-a-2d-matrix /// https://drafts.csswg.org/css-transforms/#decomposing-a-2d-matrix
fn decompose_matrix(matrix: ComputedMatrix) -> MatrixDecomposed2D { fn from(matrix: ComputedMatrix) -> MatrixDecomposed2D {
let mut row0x = matrix.m11; let mut row0x = matrix.m11;
let mut row0y = matrix.m12; let mut row0y = matrix.m12;
let mut row1x = matrix.m21; let mut row1x = matrix.m21;
@ -904,7 +952,7 @@ impl Interpolate for LengthOrNone {
row1y = -sn * m12 + cs * m22; row1y = -sn * m12 + cs * m22;
} }
let m = DecomposedMatrix { let m = InnerMatrix2D {
m11: row0x, m12: row0y, m11: row0x, m12: row0y,
m21: row1x, m22: row1y, m21: row1x, m22: row1y,
}; };
@ -918,9 +966,12 @@ impl Interpolate for LengthOrNone {
matrix: m, matrix: m,
} }
} }
}
impl From<MatrixDecomposed2D> for ComputedMatrix {
/// Recompose a matrix.
/// https://drafts.csswg.org/css-transforms/#recomposing-to-a-2d-matrix /// https://drafts.csswg.org/css-transforms/#recomposing-to-a-2d-matrix
fn recompose_matrix(decomposed: MatrixDecomposed2D) -> ComputedMatrix { fn from(decomposed: MatrixDecomposed2D) -> ComputedMatrix {
let mut computed_matrix = ComputedMatrix::identity(); let mut computed_matrix = ComputedMatrix::identity();
computed_matrix.m11 = decomposed.matrix.m11; computed_matrix.m11 = decomposed.matrix.m11;
computed_matrix.m12 = decomposed.matrix.m12; computed_matrix.m12 = decomposed.matrix.m12;
@ -930,8 +981,8 @@ impl Interpolate for LengthOrNone {
// Translate matrix. // Translate matrix.
computed_matrix.m41 = decomposed.translate.0 * decomposed.matrix.m11 + computed_matrix.m41 = decomposed.translate.0 * decomposed.matrix.m11 +
decomposed.translate.1 * decomposed.matrix.m21; decomposed.translate.1 * decomposed.matrix.m21;
computed_matrix.m42 = decomposed.translate.0 * decomposed.matrix.m11 + computed_matrix.m42 = decomposed.translate.0 * decomposed.matrix.m12 +
decomposed.translate.1 * decomposed.matrix.m21; decomposed.translate.1 * decomposed.matrix.m22;
// Rotate matrix. // Rotate matrix.
let angle = decomposed.angle.to_radians(); let angle = decomposed.angle.to_radians();
@ -944,12 +995,12 @@ impl Interpolate for LengthOrNone {
rotate_matrix.m21 = -sin_angle; rotate_matrix.m21 = -sin_angle;
rotate_matrix.m22 = cos_angle; rotate_matrix.m22 = cos_angle;
let matrix_clone = computed_matrix.clone(); let matrix_clone = computed_matrix;
// Multiplication of computed_matrix and rotate_matrix // Multiplication of computed_matrix and rotate_matrix
% for i in range(1, 5): % for i in range(1, 5):
% for j in range(1, 5): % for j in range(1, 5):
computed_matrix.m${i}${j} = (matrix_clone.m${i}1 * rotate_matrix.m1${j}) + computed_matrix.m${i}${j} = (matrix_clone.m${i}1 * rotate_matrix.m1${j}) +
(matrix_clone.m${i}2 *rotate_matrix.m2${j}) + (matrix_clone.m${i}2 * rotate_matrix.m2${j}) +
(matrix_clone.m${i}3 * rotate_matrix.m3${j}) + (matrix_clone.m${i}3 * rotate_matrix.m3${j}) +
(matrix_clone.m${i}4 * rotate_matrix.m4${j}); (matrix_clone.m${i}4 * rotate_matrix.m4${j});
% endfor % endfor
@ -962,6 +1013,7 @@ impl Interpolate for LengthOrNone {
computed_matrix.m22 *= decomposed.scale.1; computed_matrix.m22 *= decomposed.scale.1;
computed_matrix computed_matrix
} }
}
/// https://drafts.csswg.org/css-transforms/#interpolation-of-transforms /// https://drafts.csswg.org/css-transforms/#interpolation-of-transforms
impl Interpolate for TransformList { impl Interpolate for TransformList {