mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Implement transform: perspective(none)
Differential Revision: https://phabricator.services.mozilla.com/D123350
This commit is contained in:
parent
ce45f68d9c
commit
fa840e1666
4 changed files with 72 additions and 19 deletions
|
@ -1105,8 +1105,8 @@ impl Animate for ComputedTransformOperation {
|
||||||
// interpolated as defined in section Interpolation of
|
// interpolated as defined in section Interpolation of
|
||||||
// Matrices afterwards.
|
// Matrices afterwards.
|
||||||
//
|
//
|
||||||
let from = create_perspective_matrix(fd.px());
|
let from = create_perspective_matrix(fd.infinity_or(|l| l.px()));
|
||||||
let to = create_perspective_matrix(td.px());
|
let to = create_perspective_matrix(td.infinity_or(|l| l.px()));
|
||||||
|
|
||||||
let interpolated = Matrix3D::from(from).animate(&Matrix3D::from(to), procedure)?;
|
let interpolated = Matrix3D::from(from).animate(&Matrix3D::from(to), procedure)?;
|
||||||
|
|
||||||
|
@ -1115,15 +1115,17 @@ impl Animate for ComputedTransformOperation {
|
||||||
// Clamp results outside of the -1 to 0 range so that we get perspective
|
// Clamp results outside of the -1 to 0 range so that we get perspective
|
||||||
// function values between 1 and infinity.
|
// function values between 1 and infinity.
|
||||||
let used_value = if perspective_z >= 0. {
|
let used_value = if perspective_z >= 0. {
|
||||||
std::f32::INFINITY
|
transform::PerspectiveFunction::None
|
||||||
} else if perspective_z <= -1. {
|
|
||||||
1.
|
|
||||||
} else {
|
} else {
|
||||||
-1. / perspective_z
|
transform::PerspectiveFunction::Length(CSSPixelLength::new(
|
||||||
|
if perspective_z <= -1. {
|
||||||
|
1.
|
||||||
|
} else {
|
||||||
|
-1. / perspective_z
|
||||||
|
}
|
||||||
|
))
|
||||||
};
|
};
|
||||||
Ok(TransformOperation::Perspective(CSSPixelLength::new(
|
Ok(TransformOperation::Perspective(used_value))
|
||||||
used_value,
|
|
||||||
)))
|
|
||||||
},
|
},
|
||||||
_ if self.is_translate() && other.is_translate() => self
|
_ if self.is_translate() && other.is_translate() => self
|
||||||
.to_translate_3d()
|
.to_translate_3d()
|
||||||
|
@ -1202,14 +1204,18 @@ impl ComputeSquaredDistance for ComputedTransformOperation {
|
||||||
(
|
(
|
||||||
&TransformOperation::Perspective(ref fd),
|
&TransformOperation::Perspective(ref fd),
|
||||||
&TransformOperation::Perspective(ref td),
|
&TransformOperation::Perspective(ref td),
|
||||||
) => fd.compute_squared_distance(td),
|
) => {
|
||||||
|
fd.infinity_or(|l| l.px())
|
||||||
|
.compute_squared_distance(&td.infinity_or(|l| l.px()))
|
||||||
|
},
|
||||||
(&TransformOperation::Perspective(ref p), &TransformOperation::Matrix3D(ref m)) |
|
(&TransformOperation::Perspective(ref p), &TransformOperation::Matrix3D(ref m)) |
|
||||||
(&TransformOperation::Matrix3D(ref m), &TransformOperation::Perspective(ref p)) => {
|
(&TransformOperation::Matrix3D(ref m), &TransformOperation::Perspective(ref p)) => {
|
||||||
// FIXME(emilio): Is this right? Why interpolating this with
|
// FIXME(emilio): Is this right? Why interpolating this with
|
||||||
// Perspective but not with anything else?
|
// Perspective but not with anything else?
|
||||||
let mut p_matrix = Matrix3D::identity();
|
let mut p_matrix = Matrix3D::identity();
|
||||||
if p.px() >= 0. {
|
let p = p.infinity_or(|p| p.px());
|
||||||
p_matrix.m34 = -1. / p.px().max(1.);
|
if p >= 0. {
|
||||||
|
p_matrix.m34 = -1. / p.max(1.);
|
||||||
}
|
}
|
||||||
p_matrix.compute_squared_distance(&m)
|
p_matrix.compute_squared_distance(&m)
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,6 +24,9 @@ pub type Transform = generic::GenericTransform<TransformOperation>;
|
||||||
pub type TransformOrigin =
|
pub type TransformOrigin =
|
||||||
generic::GenericTransformOrigin<LengthPercentage, LengthPercentage, Length>;
|
generic::GenericTransformOrigin<LengthPercentage, LengthPercentage, Length>;
|
||||||
|
|
||||||
|
/// The computed value of the `perspective()` transform function.
|
||||||
|
pub type PerspectiveFunction = generic::PerspectiveFunction<Length>;
|
||||||
|
|
||||||
/// A vector to represent the direction vector (rotate axis) for Rotate3D.
|
/// A vector to represent the direction vector (rotate axis) for Rotate3D.
|
||||||
pub type DirectionVector = Vector3D<CSSFloat>;
|
pub type DirectionVector = Vector3D<CSSFloat>;
|
||||||
|
|
||||||
|
@ -517,7 +520,7 @@ impl ToAnimatedZero for TransformOperation {
|
||||||
Ok(generic::TransformOperation::Rotate(Angle::zero()))
|
Ok(generic::TransformOperation::Rotate(Angle::zero()))
|
||||||
},
|
},
|
||||||
generic::TransformOperation::Perspective(_) => Ok(
|
generic::TransformOperation::Perspective(_) => Ok(
|
||||||
generic::TransformOperation::Perspective(Length::new(std::f32::INFINITY))
|
generic::TransformOperation::Perspective(generic::PerspectiveFunction::None)
|
||||||
),
|
),
|
||||||
generic::TransformOperation::AccumulateMatrix { .. } |
|
generic::TransformOperation::AccumulateMatrix { .. } |
|
||||||
generic::TransformOperation::InterpolateMatrix { .. } => {
|
generic::TransformOperation::InterpolateMatrix { .. } => {
|
||||||
|
|
|
@ -141,6 +141,41 @@ fn is_same<N: PartialEq>(x: &N, y: &N) -> bool {
|
||||||
x == y
|
x == y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A value for the `perspective()` transform function, which is either a
|
||||||
|
/// non-negative `<length>` or `none`.
|
||||||
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
Debug,
|
||||||
|
Deserialize,
|
||||||
|
MallocSizeOf,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
SpecifiedValueInfo,
|
||||||
|
ToComputedValue,
|
||||||
|
ToCss,
|
||||||
|
ToResolvedValue,
|
||||||
|
ToShmem,
|
||||||
|
)]
|
||||||
|
#[repr(C, u8)]
|
||||||
|
pub enum GenericPerspectiveFunction<L> {
|
||||||
|
/// `none`
|
||||||
|
None,
|
||||||
|
/// A `<length>`.
|
||||||
|
Length(L),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L> GenericPerspectiveFunction<L> {
|
||||||
|
/// Returns `f32::INFINITY` or the result of a function on the length value.
|
||||||
|
pub fn infinity_or(&self, f: impl FnOnce(&L) -> f32) -> f32 {
|
||||||
|
match *self {
|
||||||
|
Self::None => std::f32::INFINITY,
|
||||||
|
Self::Length(ref l) => f(l),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::GenericPerspectiveFunction as PerspectiveFunction;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
Debug,
|
Debug,
|
||||||
|
@ -240,7 +275,7 @@ where
|
||||||
///
|
///
|
||||||
/// The value must be greater than or equal to zero.
|
/// The value must be greater than or equal to zero.
|
||||||
#[css(function)]
|
#[css(function)]
|
||||||
Perspective(Length),
|
Perspective(GenericPerspectiveFunction<Length>),
|
||||||
/// A intermediate type for interpolation of mismatched transform lists.
|
/// A intermediate type for interpolation of mismatched transform lists.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[css(comma, function = "interpolatematrix")]
|
#[css(comma, function = "interpolatematrix")]
|
||||||
|
@ -469,9 +504,12 @@ where
|
||||||
let theta = euclid::Angle::radians(theta.radians64());
|
let theta = euclid::Angle::radians(theta.radians64());
|
||||||
Transform3D::rotation(0., 0., 1., theta)
|
Transform3D::rotation(0., 0., 1., theta)
|
||||||
},
|
},
|
||||||
Perspective(ref d) => {
|
Perspective(ref p) => {
|
||||||
let m = create_perspective_matrix(d.to_pixel_length(None)?);
|
let px = match p {
|
||||||
m.cast()
|
PerspectiveFunction::None => std::f32::INFINITY,
|
||||||
|
PerspectiveFunction::Length(ref p) => p.to_pixel_length(None)?,
|
||||||
|
};
|
||||||
|
create_perspective_matrix(px).cast()
|
||||||
},
|
},
|
||||||
Scale3D(sx, sy, sz) => Transform3D::scale(sx.into(), sy.into(), sz.into()),
|
Scale3D(sx, sy, sz) => Transform3D::scale(sx.into(), sy.into(), sz.into()),
|
||||||
Scale(sx, sy) => Transform3D::scale(sx.into(), sy.into(), 1.),
|
Scale(sx, sy) => Transform3D::scale(sx.into(), sy.into(), 1.),
|
||||||
|
|
|
@ -238,8 +238,14 @@ impl Transform {
|
||||||
Ok(generic::TransformOperation::SkewY(theta))
|
Ok(generic::TransformOperation::SkewY(theta))
|
||||||
},
|
},
|
||||||
"perspective" => {
|
"perspective" => {
|
||||||
let d = specified::Length::parse_non_negative(context, input)?;
|
let p = match input.try_parse(|input| specified::Length::parse_non_negative(context, input)) {
|
||||||
Ok(generic::TransformOperation::Perspective(d))
|
Ok(p) => generic::PerspectiveFunction::Length(p),
|
||||||
|
Err(..) => {
|
||||||
|
input.expect_ident_matching("none")?;
|
||||||
|
generic::PerspectiveFunction::None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(generic::TransformOperation::Perspective(p))
|
||||||
},
|
},
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue