Don't apply the rotation if it cannot be normalized.

According to the spec, the computed value of transform is as specified, but
with relative lengths converted into absolute lengths, so in Gecko, we do
nothing while computing the value of rotate3d(), and do normalization in
ProcessRotate3D(). If the direction cannot be normalized, we treat it as
an identity matrix.

However, in Servo, we do normalization in to_computed_value(), and looks
like we are trying to normalize any kind of direction vectors, so according
to the spec, let's move the normalization into Fragment::transform_matrix(),
and return an identity matrix if we cannot normalize its direction vector.
This commit is contained in:
Boris Chiou 2017-08-08 14:07:28 +08:00
parent 69f02f4f7f
commit 9603266f9a
2 changed files with 12 additions and 4 deletions

View file

@ -2887,8 +2887,17 @@ impl Fragment {
for operation in operations {
let matrix = match *operation {
transform::ComputedOperation::Rotate(ax, ay, az, theta) => {
let theta = 2.0f32 * f32::consts::PI - theta.radians();
Transform3D::create_rotation(ax, ay, az, Radians::new(theta))
// https://www.w3.org/TR/css-transforms-1/#funcdef-rotate3d
// A direction vector that cannot be normalized, such as [0, 0, 0], will cause
// the rotation to not be applied, so we use identity matrix in this case.
let len = (ax * ax + ay * ay + az * az).sqrt();
if len > 0. {
let theta = 2.0f32 * f32::consts::PI - theta.radians();
Transform3D::create_rotation(ax / len, ay / len, az / len,
Radians::new(theta))
} else {
Transform3D::identity()
}
}
transform::ComputedOperation::Perspective(d) => {
create_perspective_matrix(d)

View file

@ -1416,8 +1416,7 @@ ${helpers.predefined_type(
let ay = ay.to_computed_value(context);
let az = az.to_computed_value(context);
let theta = theta.to_computed_value(context);
let len = (ax * ax + ay * ay + az * az).sqrt();
result.push(computed_value::ComputedOperation::Rotate(ax / len, ay / len, az / len, theta));
result.push(computed_value::ComputedOperation::Rotate(ax, ay, az, theta));
}
SpecifiedOperation::Skew(theta_x, None) => {
let theta_x = theta_x.to_computed_value(context);