New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stylo: Bug 1362896 - Implement ComputeSquaredDistance for TransformList #18086
Merged
+266
−29
Merged
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
a5433ad
Tweak CalcLengthOrPercentage to use pixel value.
BorisChiou 03e1794
Use f64 for Quaternion.
BorisChiou 3a5cbfb
Implement ComputeSquaredDistance for TransformList.
BorisChiou e8fad23
Implement ComputeSquaredDistance for Matrix and Perspective.
BorisChiou File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.
Loading status checks…
Implement ComputeSquaredDistance for Matrix and Perspective.
- Loading branch information
commit e8fad236effdfd3f7b7662f000d766560a8186c6
| @@ -1497,21 +1497,25 @@ fn rotate_to_matrix(x: f32, y: f32, z: f32, a: Angle) -> ComputedMatrix { | ||
| } | ||
|
|
||
| /// A 2d matrix for interpolation. | ||
| #[derive(Clone, Copy, Debug)] | ||
| #[derive(Clone, ComputeSquaredDistance, Copy, Debug)] | ||
| #[cfg_attr(feature = "servo", derive(HeapSizeOf))] | ||
| #[allow(missing_docs)] | ||
| // FIXME: We use custom derive for ComputeSquaredDistance. However, If possible, we should convert | ||
| // the InnerMatrix2D into types with physical meaning. This custom derive computes the squared | ||
| // distance from each matrix item, and this makes the result different from that in Gecko if we | ||
| // have skew factor in the ComputedMatrix. | ||
| pub struct InnerMatrix2D { | ||
| pub m11: CSSFloat, pub m12: CSSFloat, | ||
| pub m21: CSSFloat, pub m22: CSSFloat, | ||
| } | ||
|
|
||
| /// A 2d translation function. | ||
| #[derive(Clone, Copy, Debug)] | ||
| #[derive(Clone, ComputeSquaredDistance, Copy, Debug)] | ||
| #[cfg_attr(feature = "servo", derive(HeapSizeOf))] | ||
| pub struct Translate2D(f32, f32); | ||
|
|
||
| /// A 2d scale function. | ||
| #[derive(Clone, Copy, Debug)] | ||
| #[derive(Clone, ComputeSquaredDistance, Copy, Debug)] | ||
| #[cfg_attr(feature = "servo", derive(HeapSizeOf))] | ||
| pub struct Scale2D(f32, f32); | ||
|
|
||
| @@ -1606,6 +1610,20 @@ impl Animatable for MatrixDecomposed2D { | ||
| } | ||
| } | ||
|
|
||
| impl ComputeSquaredDistance for MatrixDecomposed2D { | ||
BorisChiou
Author
Contributor
|
||
| #[inline] | ||
| fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { | ||
| // Use Radian to compute the distance. | ||
| 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)?) | ||
| } | ||
| } | ||
|
|
||
| impl Animatable for ComputedMatrix { | ||
| fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> { | ||
| if self.is_3d() || other.is_3d() { | ||
| @@ -1630,6 +1648,21 @@ impl Animatable for ComputedMatrix { | ||
| } | ||
| } | ||
|
|
||
| impl ComputeSquaredDistance for ComputedMatrix { | ||
| #[inline] | ||
| fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { | ||
| if self.is_3d() || other.is_3d() { | ||
| let from = decompose_3d_matrix(*self)?; | ||
| let to = decompose_3d_matrix(*other)?; | ||
| from.compute_squared_distance(&to) | ||
| } else { | ||
| let from = MatrixDecomposed2D::from(*self); | ||
| let to = MatrixDecomposed2D::from(*other); | ||
| from.compute_squared_distance(&to) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl From<ComputedMatrix> for MatrixDecomposed2D { | ||
| /// Decompose a 2D matrix. | ||
| /// https://drafts.csswg.org/css-transforms/#decomposing-a-2d-matrix | ||
| @@ -1754,12 +1787,12 @@ impl From<ComputedMatrix> for RawGeckoGfxMatrix4x4 { | ||
| } | ||
|
|
||
| /// A 3d translation. | ||
| #[derive(Clone, Copy, Debug)] | ||
| #[derive(Clone, ComputeSquaredDistance, Copy, Debug)] | ||
| #[cfg_attr(feature = "servo", derive(HeapSizeOf))] | ||
| pub struct Translate3D(f32, f32, f32); | ||
|
|
||
| /// A 3d scale function. | ||
| #[derive(Clone, Copy, Debug)] | ||
| #[derive(Clone, ComputeSquaredDistance, Copy, Debug)] | ||
| #[cfg_attr(feature = "servo", derive(HeapSizeOf))] | ||
| pub struct Scale3D(f32, f32, f32); | ||
|
|
||
| @@ -1769,7 +1802,7 @@ pub struct Scale3D(f32, f32, f32); | ||
| pub struct Skew(f32, f32, f32); | ||
|
|
||
| /// A 3d perspective transformation. | ||
| #[derive(Clone, Copy, Debug)] | ||
| #[derive(Clone, ComputeSquaredDistance, Copy, Debug)] | ||
| #[cfg_attr(feature = "servo", derive(HeapSizeOf))] | ||
| pub struct Perspective(f32, f32, f32, f32); | ||
|
|
||
| @@ -1779,7 +1812,7 @@ pub struct Perspective(f32, f32, f32, f32); | ||
| pub struct Quaternion(f64, f64, f64, f64); | ||
|
|
||
| /// A decomposed 3d matrix. | ||
| #[derive(Clone, Copy, Debug)] | ||
| #[derive(Clone, ComputeSquaredDistance, Copy, Debug)] | ||
| #[cfg_attr(feature = "servo", derive(HeapSizeOf))] | ||
| pub struct MatrixDecomposed3D { | ||
| /// A translation function. | ||
| @@ -1827,6 +1860,17 @@ impl Quaternion { | ||
| } | ||
| } | ||
|
|
||
| impl ComputeSquaredDistance for Quaternion { | ||
| #[inline] | ||
| fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { | ||
| // Use quaternion vectors to get the angle difference. Both q1 and q2 are unit vectors, | ||
| // so we can get their angle difference by: | ||
| // cos(theta/2) = (q1 dot q2) / (|q1| * |q2|) = q1 dot q2. | ||
| let distance = self.dot(other).max(-1.0).min(1.0).acos() * 2.0; | ||
| Ok(SquaredDistance::Value(distance * distance)) | ||
| } | ||
| } | ||
|
|
||
| impl DirectionVector { | ||
| /// Create a DirectionVector. | ||
| #[inline] | ||
| @@ -2053,6 +2097,17 @@ impl Animatable for Skew { | ||
| } | ||
| } | ||
|
|
||
| impl ComputeSquaredDistance for Skew { | ||
BorisChiou
Author
Contributor
|
||
| // We have to use atan() to convert the skew factors into skew angles, so implement | ||
| // 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())?) | ||
| } | ||
| } | ||
|
|
||
| impl Animatable for Perspective { | ||
| fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> { | ||
| Ok(Perspective( | ||
| @@ -2443,10 +2498,9 @@ fn compute_transform_lists_squared_distance(from_list: &[TransformOperation], | ||
| let zero_distance = SquaredDistance::Value(0.); | ||
| let squared_distance = from_list.iter().zip(to_list.iter()).map(|(from, to)| { | ||
| match (from, to) { | ||
| (&TransformOperation::Matrix(_from), | ||
| &TransformOperation::Matrix(_to)) => { | ||
| // TODO: decompose matrix. | ||
| zero_distance | ||
| (&TransformOperation::Matrix(from), | ||
| &TransformOperation::Matrix(to)) => { | ||
| from.compute_squared_distance(&to).unwrap_or(zero_distance) | ||
| } | ||
| (&TransformOperation::Skew(fx, fy), | ||
| &TransformOperation::Skew(tx, ty)) => { | ||
| @@ -2494,19 +2548,31 @@ fn compute_transform_lists_squared_distance(from_list: &[TransformOperation], | ||
| if vector1 == vector2 { | ||
| angle1.compute_squared_distance(&angle2).unwrap_or(zero_distance) | ||
| } else { | ||
| // Use quaternion vectors to get the angle difference. Both q1 and q2 | ||
| // are unit vectors, so we can get their angle difference by | ||
| // cos(theta/2) = (q1 dot q2) / (|q1| * |q2|) = q1 dot q2. | ||
| let q1 = Quaternion::from_direction_and_angle(&vector1, angle1.radians64()); | ||
| let q2 = Quaternion::from_direction_and_angle(&vector2, angle2.radians64()); | ||
| let dist = q1.dot(&q2).max(-1.).min(1.).acos() * 2.0; | ||
| SquaredDistance::Value(dist * dist) | ||
| q1.compute_squared_distance(&q2).unwrap_or(zero_distance) | ||
| } | ||
| } | ||
| (&TransformOperation::Perspective(_fd), | ||
| &TransformOperation::Perspective(_td)) => { | ||
| // TODO: decompose matrix. | ||
| zero_distance | ||
| (&TransformOperation::Perspective(fd), | ||
| &TransformOperation::Perspective(td)) => { | ||
| let mut fd_matrix = ComputedMatrix::identity(); | ||
| let mut td_matrix = ComputedMatrix::identity(); | ||
| if fd.0 > 0 { | ||
| fd_matrix.m34 = -1. / fd.to_f32_px(); | ||
| } | ||
|
|
||
| if td.0 > 0 { | ||
| td_matrix.m34 = -1. / td.to_f32_px(); | ||
| } | ||
| fd_matrix.compute_squared_distance(&td_matrix).unwrap_or(zero_distance) | ||
| } | ||
| (&TransformOperation::Perspective(p), &TransformOperation::Matrix(m)) | | ||
| (&TransformOperation::Matrix(m), &TransformOperation::Perspective(p)) => { | ||
| let mut p_matrix = ComputedMatrix::identity(); | ||
| if p.0 > 0 { | ||
| p_matrix.m34 = -1. / p.to_f32_px(); | ||
| } | ||
| p_matrix.compute_squared_distance(&m).unwrap_or(zero_distance) | ||
| } | ||
| _ => { | ||
| // We don't support computation of distance for InterpolateMatrix and | ||
ProTip!
Use n and p to navigate between commits in a pull request.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
This implementation can be derived, I think;
Anglealready implementsComputeSquaredDistancecorrectly using radians.