Skip to content

Commit

Permalink
Cherry-pick 270294@main (84aabd2). https://bugs.webkit.org/show_bug.c…
Browse files Browse the repository at this point in the history
…gi?id=263569

    REGRESSION (266237@main): Poster circle animation is not continuous
    https://bugs.webkit.org/show_bug.cgi?id=263569
    <rdar://117209302>

    Reviewed by Simon Fraser.

    This is the same as the existing hasBig3DRotation rotation issue, where CA animates the shortest path between 3d rotations,
    because we represent them as matrices.

    Previously our computed matrices for rotate(180deg) didn’t have integer values, due to a float rounding issue during deg->rad.

    The new change computes the rotation matrix exactly, and now there’s no longer a defined direction for a 180deg rotation and
    we sometimes end up with a ‘backwards’ rotation.

    This adds an option to not do the snapping when we compute matrices for CA, so that the existing behavior is preserved.

    * Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h:
    * Source/WebCore/platform/graphics/transforms/TransformOperation.h:
    (WebCore::TransformOperation::applyUnrounded const):
    * Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp:
    (WebCore::TransformationMatrix::rotate3d):
    (WebCore::TransformationMatrix::rotate):
    (WebCore::TransformationMatrix::rotateRadians):
    * Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:

    Canonical link: https://commits.webkit.org/270294@main
  • Loading branch information
mattwoodrow authored and aperezdc committed Jan 25, 2024
1 parent 32bbe7e commit 45dfc44
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ class RotateTransformOperation final : public TransformOperation {
return false;
}

bool applyUnrounded(TransformationMatrix& transform, const FloatSize& /*borderBoxSize*/) const override
{
if (type() == TransformOperation::Type::Rotate)
transform.rotate(m_angle, TransformationMatrix::RotationSnapping::None);
else
transform.rotate3d(m_x, m_y, m_z, m_angle, TransformationMatrix::RotationSnapping::None);
return false;
}


void dump(WTF::TextStream&) const final;

RotateTransformOperation(double, double, double, double, TransformOperation::Type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ class TransformOperation : public RefCounted<TransformOperation> {

// Return true if the borderBoxSize was used in the computation, false otherwise.
virtual bool apply(TransformationMatrix&, const FloatSize& borderBoxSize) const = 0;
virtual bool applyUnrounded(TransformationMatrix& transform, const FloatSize& borderBoxSize) const
{
return apply(transform, borderBoxSize);
}

virtual Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ static double roundEpsilonToZero(double val)
return val;
}

TransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double z, double angle)
TransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double z, double angle, RotationSnapping snapping)
{
// Normalize the axis of rotation
double length = std::hypot(x, y, z);
Expand All @@ -931,8 +931,8 @@ TransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double
// Angles are in degrees. Switch to radians.
angle = deg2rad(angle);

double sinTheta = roundEpsilonToZero(sin(angle));
double cosTheta = roundEpsilonToZero(cos(angle));
double sinTheta = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(sin(angle)) : sin(angle);
double cosTheta = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(cos(angle)) : cos(angle);

TransformationMatrix mat;

Expand Down Expand Up @@ -1002,23 +1002,23 @@ TransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double
return *this;
}

TransformationMatrix& TransformationMatrix::rotate(double angle)
TransformationMatrix& TransformationMatrix::rotate(double angle, RotationSnapping snapping)
{
if (!std::fmod(angle, 360))
return *this;

return rotateRadians(deg2rad(angle));
return rotateRadians(deg2rad(angle), snapping);
}

TransformationMatrix& TransformationMatrix::rotateRadians(double angle)
TransformationMatrix& TransformationMatrix::rotateRadians(double angle, RotationSnapping snapping)
{
double sinZ = roundEpsilonToZero(sin(angle));
double cosZ = roundEpsilonToZero(cos(angle));
double sinZ = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(sin(angle)) : sin(angle);
double cosZ = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(cos(angle)) : cos(angle);
multiply({ cosZ, sinZ, -sinZ, cosZ, 0, 0 });
return *this;
}

TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, double rz)
TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, double rz, RotationSnapping snapping)
{
// Angles are in degrees. Switch to radians.
rx = deg2rad(rx);
Expand All @@ -1027,8 +1027,8 @@ TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, doubl

TransformationMatrix mat;

double sinTheta = roundEpsilonToZero(sin(rz));
double cosTheta = roundEpsilonToZero(cos(rz));
double sinTheta = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(sin(rz)) : sin(rz);
double cosTheta = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(cos(rz)) : cos(rz);

mat.m_matrix[0][0] = cosTheta;
mat.m_matrix[0][1] = sinTheta;
Expand All @@ -1045,8 +1045,8 @@ TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, doubl

TransformationMatrix rmat(mat);

sinTheta = sin(ry);
cosTheta = cos(ry);
sinTheta = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(sin(ry)) : sin(ry);
cosTheta = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(cos(ry)) : cos(ry);

mat.m_matrix[0][0] = cosTheta;
mat.m_matrix[0][1] = 0.0;
Expand All @@ -1063,8 +1063,8 @@ TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, doubl

rmat.multiply(mat);

sinTheta = sin(rx);
cosTheta = cos(rx);
sinTheta = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(sin(rx)) : sin(rx);
cosTheta = snapping == RotationSnapping::Snap90degRotations ? roundEpsilonToZero(cos(rx)) : cos(rx);

mat.m_matrix[0][0] = 1.0;
mat.m_matrix[0][1] = 0.0;
Expand Down
17 changes: 11 additions & 6 deletions Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,20 @@ class TransformationMatrix {
WEBCORE_EXPORT TransformationMatrix& scaleNonUniform(double sx, double sy);
TransformationMatrix& scale3d(double sx, double sy, double sz);

enum class RotationSnapping {
None,
Snap90degRotations,
};

// Angle is in degrees.
WEBCORE_EXPORT TransformationMatrix& rotate(double);
WEBCORE_EXPORT TransformationMatrix& rotateRadians(double);
WEBCORE_EXPORT TransformationMatrix& rotate(double, RotationSnapping = RotationSnapping::Snap90degRotations);
WEBCORE_EXPORT TransformationMatrix& rotateRadians(double, RotationSnapping = RotationSnapping::Snap90degRotations);
TransformationMatrix& rotateFromVector(double x, double y);
WEBCORE_EXPORT TransformationMatrix& rotate3d(double rx, double ry, double rz);
WEBCORE_EXPORT TransformationMatrix& rotate3d(double rx, double ry, double rz, RotationSnapping = RotationSnapping::Snap90degRotations);

// The vector (x,y,z) is normalized if it's not already. A vector of (0,0,0) uses a vector of (0,0,1).
TransformationMatrix& rotate3d(double x, double y, double z, double angle);
TransformationMatrix& rotate3d(double x, double y, double z, double angle, RotationSnapping = RotationSnapping::Snap90degRotations);

WEBCORE_EXPORT TransformationMatrix& translate(double tx, double ty);
WEBCORE_EXPORT TransformationMatrix& translate3d(double tx, double ty, double tz);

Expand Down

0 comments on commit 45dfc44

Please sign in to comment.