RESOLVED FIXED Bug 52700
Transition from perspective(500px) to 'none' is probably wrong
https://bugs.webkit.org/show_bug.cgi?id=52700
Summary Transition from perspective(500px) to 'none' is probably wrong
Simon Fraser (smfr)
Reported 2011-01-18 22:26:21 PST
The blendToIdentity clause in PerspectiveTransformOperation::blend() computes p as p = p + (1. - p) * progress; which is nonsensical. p is the perspective value (e.g. 1000), so why the 1-p?
Attachments
Testcase (693 bytes, text/html)
2011-01-19 12:30 PST, Simon Fraser (smfr)
no flags
Patch (141.74 KB, patch)
2021-11-11 04:07 PST, Martin Robinson
no flags
Patch (141.74 KB, patch)
2021-11-11 06:39 PST, Martin Robinson
no flags
Patch (146.41 KB, patch)
2021-11-30 02:47 PST, Martin Robinson
no flags
Dean Jackson
Comment 1 2011-01-19 01:07:44 PST
That's weird stuff. Identity is a zero value in the perspective part of the matrix, which is an infinite perspective(). Is that right? So should this be p + (MAX - p) * progress?
Chris Marrin
Comment 2 2011-01-19 11:43:09 PST
The formula for blendToIdentity is right: if (blendToIdentity) return PerspectiveTransformOperation::create(m_p + (1. - m_p) * progress); Because it's blending down to the identity perspective value, which is 1. The other case is: return PerspectiveTransformOperation::create(decomp.perspectiveZ ? -1.0 / decomp.perspectiveZ : 0.0); In the other case we construct from and to matrices and then let TransformationMatrix blend them. TransformationMatrix decomposes both matrices and then linearly interpolates all the decomposed values. Then composes the result into a new matrix and returns the value. PerspectiveTransformOperation::blend then decomposes that matrix and picks out the perspective Z value, which is the one we want. I did it this crazy way because perspective is not linear, so applying a linear interpolation would give us the wrong results. So I believe the code is correct, although we could certainly optimize the interpolation!
Chris Marrin
Comment 3 2011-01-19 11:50:26 PST
Simon, do you see bad behavior? It will interpolate (nonlinearly) from 500 down to the identity value of 1, which is probably wrong. We might have to change the if (blendToIdentity) case. Can you post a test case? It might be better to have the blendToIdentity case go through the same decompose/compose/decompose operation as the normal case, just using an identity matrix for the 'to' matrix. We can look at the values returned. But I think that might give you the right effect. Thinking back about it, I originally did just linearly interpolate the from and to values. The result was wrong, so I changed it to what we have today. I think I didn't take the identity case into account when I made that change.
Simon Fraser (smfr)
Comment 4 2011-01-19 12:29:59 PST
(In reply to comment #2) > The formula for blendToIdentity is right: > > if (blendToIdentity) > return PerspectiveTransformOperation::create(m_p + (1. - m_p) * progress); > > Because it's blending down to the identity perspective value, which is 1. But m_p isn't the value in the matrix; that's -1/m_p. So if perspective is 1000, this computes 1000 + (1. - 1000) * progress which makes no sense. It should really blend with infinity, but that isn't going to give sensible results either.
Simon Fraser (smfr)
Comment 5 2011-01-19 12:30:33 PST
Created attachment 79464 [details] Testcase If you hover the blue box in this testcase it seems OK, but unhover and things go whacko.
Martin Robinson
Comment 6 2021-11-11 04:06:33 PST
This doesn't reproduce in Safari any longer, but is still an issue in ports that use animations from Nicosia.
Martin Robinson
Comment 7 2021-11-11 04:07:43 PST
Martin Robinson
Comment 8 2021-11-11 06:39:01 PST
Simon Fraser (smfr)
Comment 9 2021-11-29 08:38:57 PST
Comment on attachment 443943 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=443943&action=review > Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp:59 > + const auto* fromOp = > + downcast<PerspectiveTransformOperation>(from); No wrapping. > Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp:60 > + fromPInverse = !fromOp->isIdentity() ? (1.0 / (*fromOp->floatValue())) : 0.0; Since this is repeated, put it in a lambda. > Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h:63 > + return floatValueForLength(*m_p, 1.0); Does m_p ever have calc() it in at this point?
Martin Robinson
Comment 10 2021-11-30 02:47:17 PST
Martin Robinson
Comment 11 2021-11-30 02:49:49 PST
(In reply to Simon Fraser (smfr) from comment #9) > Comment on attachment 443943 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=443943&action=review Thanks for the review. > > > Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp:59 > > + const auto* fromOp = > > + downcast<PerspectiveTransformOperation>(from); > > No wrapping. Fixed. > > Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp:60 > > + fromPInverse = !fromOp->isIdentity() ? (1.0 / (*fromOp->floatValue())) : 0.0; > > Since this is repeated, put it in a lambda. Great idea. Adding the anonymous function has simplified this code a bit. > > Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h:63 > > + return floatValueForLength(*m_p, 1.0); > > Does m_p ever have calc() it in at this point? Yes, these Lengths are always converted to numerical values in Source/WebCore/css/TransformFunctions.cpp.
EWS
Comment 12 2021-11-30 03:46:45 PST
Committed r286289 (244648@main): <https://commits.webkit.org/244648@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 445403 [details].
Radar WebKit Bug Importer
Comment 13 2021-11-30 03:47:29 PST
Note You need to log in before you can comment on or make changes to this bug.