Title: [126838] trunk/Source
Revision
126838
Author
[email protected]
Date
2012-08-27 20:39:01 -0700 (Mon, 27 Aug 2012)

Log Message

[chromium] Should accelerate rotations of >= 180 degrees
https://bugs.webkit.org/show_bug.cgi?id=94860

Reviewed by James Robinson.

Source/Platform:

When generalizing the keyframe interpolation, it became useful to append an identity transform operation,
and to ask a WebTransformOperations object if it isIdentity().

* chromium/public/WebTransformOperations.h:
(WebTransformOperations):

Source/WebCore:

WebTransformOperation now stores enough information to interpolate
without resorting to WebTransformationMatrix::blend which is both
expensive, and in the case of big rotations, error prone. For example,
we now store the axis and angle for rotations, so if two rotations are
interpolated, and they are about the same axis, we can simply
interpolate the angles.

Unit tests:
  WebTransformOperationTest.transformTypesAreUnique
  WebTransformOperationTest.matchTypesSameLength
  WebTransformOperationTest.identityAlwaysMatches
  WebTransformOperationTest.largeRotationsWithSameAxis
  WebTransformOperationTest.largeRotationsWithSameAxisInDifferentDirection
  WebTransformOperationTest.largeRotationsWithDifferentAxes
  WebTransformOperationTest.blendRotationFromIdentity
  WebTransformOperationTest.blendTranslationFromIdentity
  WebTransformOperationTest.blendScaleFromIdentity
  WebTransformOperationTest.blendSkewFromIdentity
  WebTransformOperationTest.blendPerspectiveFromIdentity
  WebTransformOperationTest.blendRotationToIdentity
  WebTransformOperationTest.blendTranslationToIdentity
  WebTransformOperationTest.blendScaleToIdentity
  WebTransformOperationTest.blendSkewToIdentity
  WebTransformOperationTest.blendPerspectiveToIdentity
  AnimationTranslationUtilTest.createTransformAnimationWithBigRotation
  AnimationTranslationUtilTest.createTransformAnimationWithBigRotationAndEmptyTransformOperationList

* platform/chromium/support/WebTransformOperations.cpp:
(std):
(WebKit::WebTransformOperation::WebTransformOperation):
(WebTransformOperation):
  Added x y z and angle.
(WebKit::WebTransformOperation::isIdentity):
  Returns true if this->matrix.isIdentity()
(WebKit::isIdentity):
  Returns true if the argument is null or ->isIdentity()
(WebKit):
(WebKit::shareSameAxis):
  A helper function that determines if two transform operations
  share the same axis. Also returns the axis and 'from' angle
  to use in the interpolation (in case the axes point in different
  directions).
(WebKit::blendDoubles):
  Linearly interpolates doubles.
(WebKit::blendTransformOperations):
  Blends two WebTransformOperation objects.
(WebKit::WebTransformOperations::blend):
  Blends two WebTransformOperations objects, taking special care
  when either isIdentity().
(WebKit::WebTransformOperations::matchesTypes):
  Was changed to reflect the fact that identity transform operations
  match anything.
(WebKit::WebTransformOperations::appendTranslate):
(WebKit::WebTransformOperations::appendRotate):
(WebKit::WebTransformOperations::appendScale):
(WebKit::WebTransformOperations::appendSkew):
(WebKit::WebTransformOperations::appendPerspective):
(WebKit::WebTransformOperations::appendIdentity):
  The 'append' functions all populate the new members in
  WebTransformOperation.
(WebKit::WebTransformOperations::isIdentity):
  Returns false iff any of its transform operations !isIdentity().
* platform/graphics/chromium/AnimationTranslationUtil.cpp:
(WebCore::toWebTransformOperations):
(WebCore::WebTransformAnimationCurve):
  Removed the >= 180 degree restriction.

Source/WebKit/chromium:

Added new unit tests:
  WebTransformOperationTest.transformTypesAreUnique
  WebTransformOperationTest.matchTypesSameLength
  WebTransformOperationTest.identityAlwaysMatches
  WebTransformOperationTest.largeRotationsWithSameAxis
  WebTransformOperationTest.largeRotationsWithSameAxisInDifferentDirection
  WebTransformOperationTest.largeRotationsWithDifferentAxes
  WebTransformOperationTest.blendRotationFromIdentity
  WebTransformOperationTest.blendTranslationFromIdentity
  WebTransformOperationTest.blendScaleFromIdentity
  WebTransformOperationTest.blendSkewFromIdentity
  WebTransformOperationTest.blendPerspectiveFromIdentity
  WebTransformOperationTest.blendRotationToIdentity
  WebTransformOperationTest.blendTranslationToIdentity
  WebTransformOperationTest.blendScaleToIdentity
  WebTransformOperationTest.blendSkewToIdentity
  WebTransformOperationTest.blendPerspectiveToIdentity
  AnimationTranslationUtilTest.createTransformAnimationWithBigRotation
  AnimationTranslationUtilTest.createTransformAnimationWithBigRotationAndEmptyTransformOperationList

* tests/AnimationTranslationUtilTest.cpp:
(WebKit::TEST):
* tests/WebTransformOperationsTest.cpp:
(TEST):
(getIdentityOperations):

Modified Paths

Diff

Modified: trunk/Source/Platform/ChangeLog (126837 => 126838)


--- trunk/Source/Platform/ChangeLog	2012-08-28 02:39:27 UTC (rev 126837)
+++ trunk/Source/Platform/ChangeLog	2012-08-28 03:39:01 UTC (rev 126838)
@@ -1,3 +1,16 @@
+2012-08-27  Ian Vollick  <[email protected]>
+
+        [chromium] Should accelerate rotations of >= 180 degrees
+        https://bugs.webkit.org/show_bug.cgi?id=94860
+
+        Reviewed by James Robinson.
+
+        When generalizing the keyframe interpolation, it became useful to append an identity transform operation,
+        and to ask a WebTransformOperations object if it isIdentity().
+
+        * chromium/public/WebTransformOperations.h:
+        (WebTransformOperations):
+
 2012-08-24  James Robinson  <[email protected]>
 
         [chromium] Clean up dependencies of WebScrollbar and WebScrollbarLayer

Modified: trunk/Source/Platform/chromium/public/WebTransformOperations.h (126837 => 126838)


--- trunk/Source/Platform/chromium/public/WebTransformOperations.h	2012-08-28 02:39:27 UTC (rev 126837)
+++ trunk/Source/Platform/chromium/public/WebTransformOperations.h	2012-08-28 03:39:01 UTC (rev 126838)
@@ -74,7 +74,10 @@
     WEBKIT_EXPORT void appendSkew(double x, double y);
     WEBKIT_EXPORT void appendPerspective(double depth);
     WEBKIT_EXPORT void appendMatrix(const WebTransformationMatrix&);
+    WEBKIT_EXPORT void appendIdentity();
 
+    WEBKIT_EXPORT bool isIdentity() const;
+
 private:
     WEBKIT_EXPORT void reset();
     WEBKIT_EXPORT void initialize();

Modified: trunk/Source/WebCore/ChangeLog (126837 => 126838)


--- trunk/Source/WebCore/ChangeLog	2012-08-28 02:39:27 UTC (rev 126837)
+++ trunk/Source/WebCore/ChangeLog	2012-08-28 03:39:01 UTC (rev 126838)
@@ -1,3 +1,77 @@
+2012-08-27  Ian Vollick  <[email protected]>
+
+        [chromium] Should accelerate rotations of >= 180 degrees
+        https://bugs.webkit.org/show_bug.cgi?id=94860
+
+        Reviewed by James Robinson.
+
+        WebTransformOperation now stores enough information to interpolate
+        without resorting to WebTransformationMatrix::blend which is both
+        expensive, and in the case of big rotations, error prone. For example,
+        we now store the axis and angle for rotations, so if two rotations are
+        interpolated, and they are about the same axis, we can simply
+        interpolate the angles.
+
+        Unit tests:
+          WebTransformOperationTest.transformTypesAreUnique
+          WebTransformOperationTest.matchTypesSameLength
+          WebTransformOperationTest.identityAlwaysMatches
+          WebTransformOperationTest.largeRotationsWithSameAxis
+          WebTransformOperationTest.largeRotationsWithSameAxisInDifferentDirection
+          WebTransformOperationTest.largeRotationsWithDifferentAxes
+          WebTransformOperationTest.blendRotationFromIdentity
+          WebTransformOperationTest.blendTranslationFromIdentity
+          WebTransformOperationTest.blendScaleFromIdentity
+          WebTransformOperationTest.blendSkewFromIdentity
+          WebTransformOperationTest.blendPerspectiveFromIdentity
+          WebTransformOperationTest.blendRotationToIdentity
+          WebTransformOperationTest.blendTranslationToIdentity
+          WebTransformOperationTest.blendScaleToIdentity
+          WebTransformOperationTest.blendSkewToIdentity
+          WebTransformOperationTest.blendPerspectiveToIdentity
+          AnimationTranslationUtilTest.createTransformAnimationWithBigRotation
+          AnimationTranslationUtilTest.createTransformAnimationWithBigRotationAndEmptyTransformOperationList
+
+        * platform/chromium/support/WebTransformOperations.cpp:
+        (std):
+        (WebKit::WebTransformOperation::WebTransformOperation):
+        (WebTransformOperation):
+          Added x y z and angle.
+        (WebKit::WebTransformOperation::isIdentity):
+          Returns true if this->matrix.isIdentity()
+        (WebKit::isIdentity):
+          Returns true if the argument is null or ->isIdentity()
+        (WebKit):
+        (WebKit::shareSameAxis):
+          A helper function that determines if two transform operations
+          share the same axis. Also returns the axis and 'from' angle
+          to use in the interpolation (in case the axes point in different
+          directions).
+        (WebKit::blendDoubles):
+          Linearly interpolates doubles.
+        (WebKit::blendTransformOperations):
+          Blends two WebTransformOperation objects.
+        (WebKit::WebTransformOperations::blend):
+          Blends two WebTransformOperations objects, taking special care
+          when either isIdentity().
+        (WebKit::WebTransformOperations::matchesTypes):
+          Was changed to reflect the fact that identity transform operations
+          match anything.
+        (WebKit::WebTransformOperations::appendTranslate):
+        (WebKit::WebTransformOperations::appendRotate):
+        (WebKit::WebTransformOperations::appendScale):
+        (WebKit::WebTransformOperations::appendSkew):
+        (WebKit::WebTransformOperations::appendPerspective):
+        (WebKit::WebTransformOperations::appendIdentity):
+          The 'append' functions all populate the new members in
+          WebTransformOperation.
+        (WebKit::WebTransformOperations::isIdentity):
+          Returns false iff any of its transform operations !isIdentity().
+        * platform/graphics/chromium/AnimationTranslationUtil.cpp:
+        (WebCore::toWebTransformOperations):
+        (WebCore::WebTransformAnimationCurve):
+          Removed the >= 180 degree restriction.
+
 2012-08-27  Sheriff Bot  <[email protected]>
 
         Unreviewed, rolling out r126836.

Modified: trunk/Source/WebCore/platform/chromium/support/WebTransformOperations.cpp (126837 => 126838)


--- trunk/Source/WebCore/platform/chromium/support/WebTransformOperations.cpp	2012-08-28 02:39:27 UTC (rev 126837)
+++ trunk/Source/WebCore/platform/chromium/support/WebTransformOperations.cpp	2012-08-28 03:39:01 UTC (rev 126838)
@@ -26,8 +26,15 @@
 
 #include <public/WebTransformOperations.h>
 
+#include <algorithm>
 #include <wtf/Vector.h>
 
+using namespace std;
+
+namespace {
+const double EPSILON = 1e-4;
+}
+
 namespace WebKit {
 
 struct WebTransformOperation {
@@ -37,11 +44,43 @@
         WebTransformOperationScale,
         WebTransformOperationSkew,
         WebTransformOperationPerspective,
-        WebTransformOperationMatrix
+        WebTransformOperationMatrix,
+        WebTransformOperationIdentity
     };
 
+    WebTransformOperation()
+        : type(WebTransformOperationIdentity)
+    {
+    }
+
     Type type;
     WebTransformationMatrix matrix;
+
+    union {
+        double perspectiveDepth;
+
+        struct {
+            double x, y;
+        } skew;
+
+        struct {
+             double x, y, z;
+        } scale;
+
+        struct {
+            double x, y, z;
+        } translate;
+
+        struct {
+            struct {
+                double x, y, z;
+            } axis;
+
+            double angle;
+        } rotate;
+    };
+
+    bool isIdentity() const { return matrix.isIdentity(); }
 };
 
 class WebTransformOperationsPrivate {
@@ -57,13 +96,165 @@
     return toReturn;
 }
 
+static bool isIdentity(const WebTransformOperation* operation)
+{
+    return !operation || operation->isIdentity();
+}
+
+static bool shareSameAxis(const WebTransformOperation* from, const WebTransformOperation* to, double& axisX, double& axisY, double& axisZ, double& angleFrom)
+{
+    if (isIdentity(from) && isIdentity(to))
+        return false;
+
+    if (isIdentity(from) && !isIdentity(to)) {
+        axisX = to->rotate.axis.x;
+        axisY = to->rotate.axis.y;
+        axisZ = to->rotate.axis.z;
+        angleFrom = 0;
+        return true;
+    }
+
+    if (!isIdentity(from) && isIdentity(to)) {
+        axisX = from->rotate.axis.x;
+        axisY = from->rotate.axis.y;
+        axisZ = from->rotate.axis.z;
+        angleFrom = from->rotate.angle;
+        return true;
+    }
+
+    double length2 = from->rotate.axis.x * from->rotate.axis.x + from->rotate.axis.y * from->rotate.axis.y + from->rotate.axis.z * from->rotate.axis.z;
+    double otherLength2 = to->rotate.axis.x * to->rotate.axis.x + to->rotate.axis.y * to->rotate.axis.y + to->rotate.axis.z * to->rotate.axis.z;
+
+    if (length2 <= EPSILON || otherLength2 <= EPSILON)
+        return false;
+
+    double dot = to->rotate.axis.x * from->rotate.axis.x + to->rotate.axis.y * from->rotate.axis.y + to->rotate.axis.z * from->rotate.axis.z;
+    double error = fabs(1.0 - (dot * dot) / (length2 * otherLength2));
+    bool result = error < EPSILON;
+    if (result) {
+        axisX = to->rotate.axis.x;
+        axisY = to->rotate.axis.y;
+        axisZ = to->rotate.axis.z;
+        // If the axes are pointing in opposite directions, we need to reverse
+        // the angle.
+        angleFrom = dot > 0 ? from->rotate.angle : -from->rotate.angle;
+    }
+    return result;
+}
+
+static double blendDoubles(double from, double to, double progress)
+{
+    return from * (1 - progress) + to * progress;
+}
+
+static WebTransformationMatrix blendTransformOperations(const WebTransformOperation* from, const WebTransformOperation* to, double progress)
+{
+    WebTransformationMatrix toReturn;
+
+    if (isIdentity(from) && isIdentity(to))
+        return toReturn;
+
+    WebTransformOperation::Type interpolationType = WebTransformOperation::WebTransformOperationIdentity;
+    if (isIdentity(to))
+        interpolationType = from->type;
+    else
+        interpolationType = to->type;
+
+    switch (interpolationType) {
+    case WebTransformOperation::WebTransformOperationTranslate: {
+        double fromX = isIdentity(from) ? 0 : from->translate.x;
+        double fromY = isIdentity(from) ? 0 : from->translate.y;
+        double fromZ = isIdentity(from) ? 0 : from->translate.z;
+        double toX = isIdentity(to) ? 0 : to->translate.x;
+        double toY = isIdentity(to) ? 0 : to->translate.y;
+        double toZ = isIdentity(to) ? 0 : to->translate.z;
+        toReturn.translate3d(blendDoubles(fromX, toX, progress),
+                             blendDoubles(fromY, toY, progress),
+                             blendDoubles(fromZ, toZ, progress));
+        break;
+    }
+    case WebTransformOperation::WebTransformOperationRotate: {
+        double axisX = 0;
+        double axisY = 0;
+        double axisZ = 1;
+        double fromAngle = 0;
+        double toAngle = isIdentity(to) ? 0 : to->rotate.angle;
+        if (shareSameAxis(from, to, axisX, axisY, axisZ, fromAngle))
+            toReturn.rotate3d(axisX, axisY, axisZ, blendDoubles(fromAngle, toAngle, progress));
+        else {
+            WebTransformationMatrix toMatrix;
+            if (!isIdentity(to))
+                toMatrix = to->matrix;
+            WebTransformationMatrix fromMatrix;
+            if (!isIdentity(from))
+                fromMatrix = from->matrix;
+            toReturn = toMatrix;
+            toReturn.blend(fromMatrix, progress);
+        }
+        break;
+    }
+    case WebTransformOperation::WebTransformOperationScale: {
+        double fromX = isIdentity(from) ? 1 : from->scale.x;
+        double fromY = isIdentity(from) ? 1 : from->scale.y;
+        double fromZ = isIdentity(from) ? 1 : from->scale.z;
+        double toX = isIdentity(to) ? 1 : to->scale.x;
+        double toY = isIdentity(to) ? 1 : to->scale.y;
+        double toZ = isIdentity(to) ? 1 : to->scale.z;
+        toReturn.scale3d(blendDoubles(fromX, toX, progress),
+                         blendDoubles(fromY, toY, progress),
+                         blendDoubles(fromZ, toZ, progress));
+        break;
+    }
+    case WebTransformOperation::WebTransformOperationSkew: {
+        double fromX = isIdentity(from) ? 0 : from->skew.x;
+        double fromY = isIdentity(from) ? 0 : from->skew.y;
+        double toX = isIdentity(to) ? 0 : to->skew.x;
+        double toY = isIdentity(to) ? 0 : to->skew.y;
+        toReturn.skewX(blendDoubles(fromX, toX, progress));
+        toReturn.skewY(blendDoubles(fromY, toY, progress));
+        break;
+    }
+    case WebTransformOperation::WebTransformOperationPerspective: {
+        double fromPerspectiveDepth = isIdentity(from) ? numeric_limits<double>::max() : from->perspectiveDepth;
+        double toPerspectiveDepth = isIdentity(to) ? numeric_limits<double>::max() : to->perspectiveDepth;
+        toReturn.applyPerspective(blendDoubles(fromPerspectiveDepth, toPerspectiveDepth, progress));
+        break;
+    }
+    case WebTransformOperation::WebTransformOperationMatrix: {
+        WebTransformationMatrix toMatrix;
+        if (!isIdentity(to))
+            toMatrix = to->matrix;
+        WebTransformationMatrix fromMatrix;
+        if (!isIdentity(from))
+            fromMatrix = from->matrix;
+        toReturn = toMatrix;
+        toReturn.blend(fromMatrix, progress);
+        break;
+    }
+    case WebTransformOperation::WebTransformOperationIdentity:
+        // Do nothing.
+        break;
+    }
+
+    return toReturn;
+}
+
 WebTransformationMatrix WebTransformOperations::blend(const WebTransformOperations& from, double progress) const
 {
     WebTransformationMatrix toReturn;
+    bool fromIdentity = from.isIdentity();
+    bool toIdentity = isIdentity();
+    if (fromIdentity && toIdentity)
+        return toReturn;
+
     if (matchesTypes(from)) {
-        for (size_t i = 0; i < m_private->operations.size(); ++i) {
-            WebTransformationMatrix blended = m_private->operations[i].matrix;
-            blended.blend(from.m_private->operations[i].matrix, progress);
+        size_t numOperations = max(fromIdentity ? 0 : from.m_private->operations.size(),
+                                   toIdentity ? 0 : m_private->operations.size());
+        for (size_t i = 0; i < numOperations; ++i) {
+            WebTransformationMatrix blended = blendTransformOperations(
+                fromIdentity ? 0 : &from.m_private->operations[i],
+                toIdentity ? 0 : &m_private->operations[i],
+                progress);
             toReturn.multiply(blended);
         }
     } else {
@@ -76,11 +267,16 @@
 
 bool WebTransformOperations::matchesTypes(const WebTransformOperations& other) const
 {
+    if (isIdentity() || other.isIdentity())
+        return true;
+
     if (m_private->operations.size() != other.m_private->operations.size())
         return false;
 
     for (size_t i = 0; i < m_private->operations.size(); ++i) {
-        if (m_private->operations[i].type != other.m_private->operations[i].type)
+        if (m_private->operations[i].type != other.m_private->operations[i].type
+            && !m_private->operations[i].isIdentity()
+            && !other.m_private->operations[i].isIdentity())
             return false;
     }
 
@@ -92,6 +288,9 @@
     WebTransformOperation toAdd;
     toAdd.matrix.translate3d(x, y, z);
     toAdd.type = WebTransformOperation::WebTransformOperationTranslate;
+    toAdd.translate.x = x;
+    toAdd.translate.y = y;
+    toAdd.translate.z = z;
     m_private->operations.append(toAdd);
 }
 
@@ -100,6 +299,10 @@
     WebTransformOperation toAdd;
     toAdd.matrix.rotate3d(x, y, z, degrees);
     toAdd.type = WebTransformOperation::WebTransformOperationRotate;
+    toAdd.rotate.axis.x = x;
+    toAdd.rotate.axis.y = y;
+    toAdd.rotate.axis.z = z;
+    toAdd.rotate.angle = degrees;
     m_private->operations.append(toAdd);
 }
 
@@ -108,6 +311,9 @@
     WebTransformOperation toAdd;
     toAdd.matrix.scale3d(x, y, z);
     toAdd.type = WebTransformOperation::WebTransformOperationScale;
+    toAdd.scale.x = x;
+    toAdd.scale.y = y;
+    toAdd.scale.z = z;
     m_private->operations.append(toAdd);
 }
 
@@ -117,6 +323,8 @@
     toAdd.matrix.skewX(x);
     toAdd.matrix.skewY(y);
     toAdd.type = WebTransformOperation::WebTransformOperationSkew;
+    toAdd.skew.x = x;
+    toAdd.skew.y = y;
     m_private->operations.append(toAdd);
 }
 
@@ -125,6 +333,7 @@
     WebTransformOperation toAdd;
     toAdd.matrix.applyPerspective(depth);
     toAdd.type = WebTransformOperation::WebTransformOperationPerspective;
+    toAdd.perspectiveDepth = depth;
     m_private->operations.append(toAdd);
 }
 
@@ -136,6 +345,20 @@
     m_private->operations.append(toAdd);
 }
 
+void WebTransformOperations::appendIdentity()
+{
+    m_private->operations.append(WebTransformOperation());
+}
+
+bool WebTransformOperations::isIdentity() const
+{
+    for (size_t i = 0; i < m_private->operations.size(); ++i) {
+        if (!m_private->operations[i].isIdentity())
+            return false;
+    }
+    return true;
+}
+
 void WebTransformOperations::reset()
 {
     m_private.reset(0);

Modified: trunk/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp (126837 => 126838)


--- trunk/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp	2012-08-28 02:39:27 UTC (rev 126837)
+++ trunk/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp	2012-08-28 03:39:01 UTC (rev 126838)
@@ -113,6 +113,8 @@
             break;
         }
         case TransformOperation::IDENTITY:
+            webTransformOperations.appendIdentity();
+            break;
         case TransformOperation::NONE:
             // Do nothing.
             break;
@@ -145,51 +147,9 @@
         || transformType == TransformOperation::ROTATE_3D;
 }
 
-bool causesRotationOfAtLeast180Degrees(const TransformAnimationValue* value, const TransformAnimationValue* lastValue)
-{
-    if (!lastValue)
-        return false;
-
-    const TransformOperations& operations = *value->value();
-    const TransformOperations& lastOperations = *lastValue->value();
-
-    // We'll be doing matrix interpolation in this case. No risk of incorrect rotations here.
-    if (operations.size() && lastOperations.size() && !operations.operationsMatch(lastOperations))
-        return false;
-
-    size_t numOperations = max(operations.size(), lastOperations.size());
-    for (size_t i = 0; i < numOperations; ++i) {
-        float angle = 0;
-        if (i < operations.size()) {
-            if (!isRotationType(operations.operations()[i]->getOperationType()))
-                continue;
-
-            RotateTransformOperation* rotation = static_cast<RotateTransformOperation*>(operations.operations()[i].get());
-            angle = rotation->angle();
-        }
-
-        float lastAngle = 0;
-        if (i < lastOperations.size()) {
-            if (!isRotationType(lastOperations.operations()[i]->getOperationType()))
-                continue;
-
-            RotateTransformOperation* lastRotation = static_cast<RotateTransformOperation*>(lastOperations.operations()[i].get());
-            lastAngle = lastRotation->angle();
-        }
-
-        if (fabs(angle - lastAngle) >= 180)
-            return true;
-    }
-
-    return false;
-}
-
 template <>
 bool appendKeyframeWithStandardTimingFunction<TransformAnimationValue, WebTransformKeyframe, WebTransformAnimationCurve>(WebTransformAnimationCurve* curve, double keyTime, const TransformAnimationValue* value, const TransformAnimationValue* lastValue, WebKit::WebAnimationCurve::TimingFunctionType timingFunctionType, const FloatSize& boxSize)
 {
-    if (causesRotationOfAtLeast180Degrees(value, lastValue))
-        return false;
-
     WebTransformOperations operations = toWebTransformOperations(*value->value(), boxSize);
     if (operations.apply().isInvertible()) {
         curve->add(WebTransformKeyframe(keyTime, operations), timingFunctionType);
@@ -201,9 +161,6 @@
 template <>
 bool appendKeyframeWithCustomBezierTimingFunction<TransformAnimationValue, WebTransformKeyframe, WebTransformAnimationCurve>(WebTransformAnimationCurve* curve, double keyTime, const TransformAnimationValue* value, const TransformAnimationValue* lastValue, double x1, double y1, double x2, double y2, const FloatSize& boxSize)
 {
-    if (causesRotationOfAtLeast180Degrees(value, lastValue))
-        return false;
-
     WebTransformOperations operations = toWebTransformOperations(*value->value(), boxSize);
     if (operations.apply().isInvertible()) {
         curve->add(WebTransformKeyframe(keyTime, operations), x1, y1, x2, y2);

Modified: trunk/Source/WebKit/chromium/ChangeLog (126837 => 126838)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-08-28 02:39:27 UTC (rev 126837)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-08-28 03:39:01 UTC (rev 126838)
@@ -1,3 +1,36 @@
+2012-08-27  Ian Vollick  <[email protected]>
+
+        [chromium] Should accelerate rotations of >= 180 degrees
+        https://bugs.webkit.org/show_bug.cgi?id=94860
+
+        Reviewed by James Robinson.
+
+        Added new unit tests:
+          WebTransformOperationTest.transformTypesAreUnique
+          WebTransformOperationTest.matchTypesSameLength
+          WebTransformOperationTest.identityAlwaysMatches
+          WebTransformOperationTest.largeRotationsWithSameAxis
+          WebTransformOperationTest.largeRotationsWithSameAxisInDifferentDirection
+          WebTransformOperationTest.largeRotationsWithDifferentAxes
+          WebTransformOperationTest.blendRotationFromIdentity
+          WebTransformOperationTest.blendTranslationFromIdentity
+          WebTransformOperationTest.blendScaleFromIdentity
+          WebTransformOperationTest.blendSkewFromIdentity
+          WebTransformOperationTest.blendPerspectiveFromIdentity
+          WebTransformOperationTest.blendRotationToIdentity
+          WebTransformOperationTest.blendTranslationToIdentity
+          WebTransformOperationTest.blendScaleToIdentity
+          WebTransformOperationTest.blendSkewToIdentity
+          WebTransformOperationTest.blendPerspectiveToIdentity
+          AnimationTranslationUtilTest.createTransformAnimationWithBigRotation
+          AnimationTranslationUtilTest.createTransformAnimationWithBigRotationAndEmptyTransformOperationList
+
+        * tests/AnimationTranslationUtilTest.cpp:
+        (WebKit::TEST):
+        * tests/WebTransformOperationsTest.cpp:
+        (TEST):
+        (getIdentityOperations):
+
 2012-08-27  Sheriff Bot  <[email protected]>
 
         Unreviewed, rolling out r126836.

Modified: trunk/Source/WebKit/chromium/tests/AnimationTranslationUtilTest.cpp (126837 => 126838)


--- trunk/Source/WebKit/chromium/tests/AnimationTranslationUtilTest.cpp	2012-08-28 02:39:27 UTC (rev 126837)
+++ trunk/Source/WebKit/chromium/tests/AnimationTranslationUtilTest.cpp	2012-08-28 03:39:01 UTC (rev 126838)
@@ -96,7 +96,7 @@
     RefPtr<Animation> animation = Animation::create();
     animation->setDuration(duration);
 
-    EXPECT_FALSE(animationCanBeTranslated(values, animation.get()));
+    EXPECT_TRUE(animationCanBeTranslated(values, animation.get()));
 }
 
 TEST(AnimationTranslationUtilTest, createTransformAnimationWithBigRotationAndEmptyTransformOperationList)
@@ -114,7 +114,7 @@
     RefPtr<Animation> animation = Animation::create();
     animation->setDuration(duration);
 
-    EXPECT_FALSE(animationCanBeTranslated(values, animation.get()));
+    EXPECT_TRUE(animationCanBeTranslated(values, animation.get()));
 }
 
 TEST(AnimationTranslationUtilTest, createTransformAnimationWithRotationInvolvingNegativeAngles)

Modified: trunk/Source/WebKit/chromium/tests/WebTransformOperationsTest.cpp (126837 => 126838)


--- trunk/Source/WebKit/chromium/tests/WebTransformOperationsTest.cpp	2012-08-28 02:39:27 UTC (rev 126837)
+++ trunk/Source/WebKit/chromium/tests/WebTransformOperationsTest.cpp	2012-08-28 03:39:01 UTC (rev 126838)
@@ -35,6 +35,7 @@
 #include <wtf/PassOwnPtr.h>
 #include <wtf/Vector.h>
 
+using namespace std;
 using namespace WebKit;
 
 TEST(WebTransformOperationTest, transformTypesAreUnique)
@@ -42,19 +43,19 @@
     Vector<OwnPtr<WebTransformOperations> > transforms;
 
     WebTransformOperations* toAdd = new WebTransformOperations();
-    toAdd->appendTranslate(0, 0, 0);
+    toAdd->appendTranslate(1, 0, 0);
     transforms.append(adoptPtr(toAdd));
 
     toAdd = new WebTransformOperations();
-    toAdd->appendRotate(0, 0, 1, 0);
+    toAdd->appendRotate(0, 0, 1, 2);
     transforms.append(adoptPtr(toAdd));
 
     toAdd = new WebTransformOperations();
-    toAdd->appendScale(1, 1, 1);
+    toAdd->appendScale(2, 2, 2);
     transforms.append(adoptPtr(toAdd));
 
     toAdd = new WebTransformOperations();
-    toAdd->appendSkew(0, 0);
+    toAdd->appendSkew(1, 0);
     transforms.append(adoptPtr(toAdd));
 
     toAdd = new WebTransformOperations();
@@ -72,19 +73,19 @@
 TEST(WebTransformOperationTest, matchTypesSameLength)
 {
     WebTransformOperations translates;
-    translates.appendTranslate(0, 0, 0);
-    translates.appendTranslate(0, 0, 0);
-    translates.appendTranslate(0, 0, 0);
+    translates.appendTranslate(1, 0, 0);
+    translates.appendTranslate(1, 0, 0);
+    translates.appendTranslate(1, 0, 0);
 
     WebTransformOperations skews;
-    skews.appendSkew(0, 0);
-    skews.appendSkew(0, 0);
-    skews.appendSkew(0, 0);
+    skews.appendSkew(0, 2);
+    skews.appendSkew(0, 2);
+    skews.appendSkew(0, 2);
 
     WebTransformOperations translates2;
-    translates2.appendTranslate(0, 0, 0);
-    translates2.appendTranslate(0, 0, 0);
-    translates2.appendTranslate(0, 0, 0);
+    translates2.appendTranslate(0, 2, 0);
+    translates2.appendTranslate(0, 2, 0);
+    translates2.appendTranslate(0, 2, 0);
 
     WebTransformOperations translates3 = translates2;
 
@@ -96,22 +97,84 @@
 TEST(WebTransformOperationTest, matchTypesDifferentLength)
 {
     WebTransformOperations translates;
-    translates.appendTranslate(0, 0, 0);
-    translates.appendTranslate(0, 0, 0);
-    translates.appendTranslate(0, 0, 0);
+    translates.appendTranslate(1, 0, 0);
+    translates.appendTranslate(1, 0, 0);
+    translates.appendTranslate(1, 0, 0);
 
     WebTransformOperations skews;
-    skews.appendSkew(0, 0);
-    skews.appendSkew(0, 0);
+    skews.appendSkew(2, 0);
+    skews.appendSkew(2, 0);
 
     WebTransformOperations translates2;
-    translates2.appendTranslate(0, 0, 0);
-    translates2.appendTranslate(0, 0, 0);
+    translates2.appendTranslate(0, 2, 0);
+    translates2.appendTranslate(0, 2, 0);
 
     EXPECT_FALSE(translates.matchesTypes(skews));
     EXPECT_FALSE(translates.matchesTypes(translates2));
 }
 
+void getIdentityOperations(Vector<OwnPtr<WebTransformOperations> >* operations)
+{
+    WebTransformOperations* toAdd = new WebTransformOperations();
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendTranslate(0, 0, 0);
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendTranslate(0, 0, 0);
+    toAdd->appendTranslate(0, 0, 0);
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendScale(1, 1, 1);
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendScale(1, 1, 1);
+    toAdd->appendScale(1, 1, 1);
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendSkew(0, 0);
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendSkew(0, 0);
+    toAdd->appendSkew(0, 0);
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendRotate(0, 0, 1, 0);
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendRotate(0, 0, 1, 0);
+    toAdd->appendRotate(0, 0, 1, 0);
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendMatrix(WebTransformationMatrix());
+    operations->append(adoptPtr(toAdd));
+
+    toAdd = new WebTransformOperations();
+    toAdd->appendMatrix(WebTransformationMatrix());
+    toAdd->appendMatrix(WebTransformationMatrix());
+    operations->append(adoptPtr(toAdd));
+}
+
+TEST(WebTransformOperationTest, identityAlwaysMatches)
+{
+    Vector<OwnPtr<WebTransformOperations> > operations;
+    getIdentityOperations(&operations);
+
+    for (size_t i = 0; i < operations.size(); ++i) {
+        for (size_t j = 0; j < operations.size(); ++j)
+            EXPECT_TRUE(operations[i]->matchesTypes(*operations[j]));
+    }
+}
+
 TEST(WebTransformOperationTest, applyTranslate)
 {
     double x = 1;
@@ -339,3 +402,238 @@
 
     EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operationsTo.blend(operationsFrom, progress));
 }
+
+TEST(WebTransformOperationTest, largeRotationsWithSameAxis)
+{
+    WebTransformOperations operationsFrom;
+    operationsFrom.appendRotate(0, 0, 1, 0);
+
+    WebTransformOperations operationsTo;
+    operationsTo.appendRotate(0, 0, 2, 360);
+
+    double progress = 0.5;
+
+    WebTransformationMatrix expected;
+    expected.rotate3d(0, 0, 1, 180);
+
+    EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operationsTo.blend(operationsFrom, progress));
+}
+
+TEST(WebTransformOperationTest, largeRotationsWithSameAxisInDifferentDirection)
+{
+    WebTransformOperations operationsFrom;
+    operationsFrom.appendRotate(0, 0, 1, 180);
+
+    WebTransformOperations operationsTo;
+    operationsTo.appendRotate(0, 0, -1, 180);
+
+    double progress = 0.5;
+
+    WebTransformationMatrix expected;
+
+    EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operationsTo.blend(operationsFrom, progress));
+}
+
+TEST(WebTransformOperationTest, largeRotationsWithDifferentAxes)
+{
+    WebTransformOperations operationsFrom;
+    operationsFrom.appendRotate(0, 0, 1, 180);
+
+    WebTransformOperations operationsTo;
+    operationsTo.appendRotate(0, 1, 0, 180);
+
+    double progress = 0.5;
+    WebTransformationMatrix matrixFrom;
+    matrixFrom.rotate3d(0, 0, 1, 180);
+
+    WebTransformationMatrix matrixTo;
+    matrixTo.rotate3d(0, 1, 0, 180);
+
+    WebTransformationMatrix expected = matrixTo;
+    expected.blend(matrixFrom, progress);
+
+    EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operationsTo.blend(operationsFrom, progress));
+}
+
+TEST(WebTransformOperationTest, blendRotationFromIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendRotate(0, 0, 1, 360);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.rotate3d(0, 0, 1, 180);
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.blend(*identityOperations[i], progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendTranslationFromIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendTranslate(2, 2, 2);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.translate3d(1, 1, 1);
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.blend(*identityOperations[i], progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendScaleFromIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendScale(3, 3, 3);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.scale3d(2, 2, 2);
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.blend(*identityOperations[i], progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendSkewFromIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendSkew(2, 2);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.skewX(1);
+        expected.skewY(1);
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.blend(*identityOperations[i], progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendPerspectiveFromIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendPerspective(1000);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.applyPerspective(500 + 0.5 * numeric_limits<double>::max());
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, operations.blend(*identityOperations[i], progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendRotationToIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendRotate(0, 0, 1, 360);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.rotate3d(0, 0, 1, 180);
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, identityOperations[i]->blend(operations, progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendTranslationToIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendTranslate(2, 2, 2);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.translate3d(1, 1, 1);
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, identityOperations[i]->blend(operations, progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendScaleToIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendScale(3, 3, 3);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.scale3d(2, 2, 2);
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, identityOperations[i]->blend(operations, progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendSkewToIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendSkew(2, 2);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.skewX(1);
+        expected.skewY(1);
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, identityOperations[i]->blend(operations, progress));
+    }
+}
+
+TEST(WebTransformOperationTest, blendPerspectiveToIdentity)
+{
+    Vector<OwnPtr<WebTransformOperations> > identityOperations;
+    getIdentityOperations(&identityOperations);
+
+    for (size_t i = 0; i < identityOperations.size(); ++i) {
+        WebTransformOperations operations;
+        operations.appendPerspective(1000);
+
+        double progress = 0.5;
+
+        WebTransformationMatrix expected;
+        expected.applyPerspective(500 + 0.5 * numeric_limits<double>::max());
+
+        EXPECT_TRANSFORMATION_MATRIX_EQ(expected, identityOperations[i]->blend(operations, progress));
+    }
+}
+
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to