In the // Optimize for single axis rotation clause, why does it only check if 'fromOp' is axis-aligned. Shouldn't it also check that |this| is axis-aligned in the same way?
Created attachment 157366 [details] Shows error on Chrome I wrote a simple test case. It is indeed a bug not to check the resulting rotation as well. Actually it does not affect Safari, since it seems to use the logic of CoreAnimation. But you can see the problem in Chrome. The element just gets rotated by the y-axis of the initial transform and does not animate around the x-axis as well. It jumps to the correct result after the animation. I wonder why we just optimize for vectors of the length of 1? If the vectors go in the same direction, the length doesn't matter. So it should be more like: ((fromOp->m_x == m_x) == 0 && (fromOp->m_y == m_y) == 0 && (fromOp->m_z == m_z) > 0) for the z-axis and similar for every axis. It should also be possible to use the fast track if both vectors are negative.
Could we do something like this? // Optimize for single axis rotation if (!fromOp || hasSameAxis(*fromOp)) { double fromAngle = fromOp ? fromOp->m_angle : 0; return RotateTransformOperation::create(m_x, m_y, m_z, WebCore::blend(fromAngle, m_angle, progress), m_type); } where, bool RotateTransformOperation::hasSameAxis(const RotateTransformOperation& other) { double length = sqrt(m_x * m_x + m_y * m_y + m_z * m_z); double otherLength = sqrt(other.m_x * other.m_x + other.m_y * other.m_y + other.m_z * other.m_z); if (length <= EPSILON || otherLength <= EPSILON) return false; double dot = other.m_x * m_x + other.m_y * m_y + other.m_z * m_z; double error = fabs(1.0 - dot / (length * otherLength)); return error < EPSILON; }
Changed test in JSFiddle (not removed -webkit-): https://jsfiddle.net/9Lonmyxr/ WebKit ToT and Chrome Canary 120 seems to work similar or I am missing anything?