Index: cc/math_util.cc |
diff --git a/cc/math_util.cc b/cc/math_util.cc |
index 606f67bf482b34e7ffbb9cdf35ffb2d039ccb401..2f885f865c2b0be25dd81655164e4a40fa295000 100644 |
--- a/cc/math_util.cc |
+++ b/cc/math_util.cc |
@@ -20,6 +20,7 @@ namespace cc { |
const double MathUtil::PI_DOUBLE = 3.14159265358979323846; |
const float MathUtil::PI_FLOAT = 3.14159265358979323846f; |
+const double MathUtil::EPSILON = 1e-9; |
static HomogeneousCoordinate projectHomogeneousPoint(const WebTransformationMatrix& transform, const gfx::PointF& p) |
{ |
@@ -395,4 +396,161 @@ gfx::Vector2dF MathUtil::projectVector(gfx::Vector2dF source, gfx::Vector2dF des |
return gfx::Vector2dF(projectedLength * destination.x(), projectedLength * destination.y()); |
} |
+bool MathUtil::isInvertible(const gfx::Transform& transform) |
+{ |
+ const SkMatrix44& matrix = transform.matrix(); |
+ double determinant = matrix.determinant(); |
+ return abs(determinant) > EPSILON; |
+} |
+ |
+bool MathUtil::isBackFaceVisible(const gfx::Transform&) |
+{ |
+ // TODO (shawnsingh): to be implemented in a follow up patch very soon. |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+bool MathUtil::isIdentity(const gfx::Transform& transform) |
+{ |
+ return transform.matrix().isIdentity(); |
+} |
+ |
+bool MathUtil::isIdentityOrTranslation(const gfx::Transform& transform) |
+{ |
+ const SkMatrix44& matrix = transform.matrix(); |
+ |
+ bool hasNoPerspective = !matrix.getDouble(3, 0) && !matrix.getDouble(3, 1) && !matrix.getDouble(3, 2) && (matrix.getDouble(3, 3) == 1); |
+ bool hasNoRotationOrSkew = !matrix.getDouble(0, 1) && !matrix.getDouble(0, 2) && !matrix.getDouble(1, 0) && |
+ !matrix.getDouble(1, 2) && !matrix.getDouble(2, 0) && !matrix.getDouble(2, 1); |
+ bool hasNoScale = matrix.getDouble(0, 0) == 1 && matrix.getDouble(1, 1) == 1 && matrix.getDouble(2, 2) == 1; |
+ |
+ return hasNoPerspective && hasNoRotationOrSkew && hasNoScale; |
+} |
+ |
+bool MathUtil::hasPerspective(const gfx::Transform& transform) |
+{ |
+ // Mathematically it is a bit too strict to expect the 4th element to be |
+ // equal to 1. However, the only non-perspective case where this element |
+ // becomes non-1 is when it was explicitly initialized. In that case it |
+ // still causes us to have a nontrivial divide-by-w, so we count it as |
+ // being perspective here. |
+ const SkMatrix44& matrix = transform.matrix(); |
+ return matrix.getDouble(3, 0) || matrix.getDouble(3, 1) || matrix.getDouble(3, 2) || (matrix.getDouble(3, 3) != 1); |
+} |
+ |
+void MathUtil::makeIdentity(gfx::Transform* transform) |
+{ |
+ transform->matrix().setIdentity(); |
+} |
+ |
+void MathUtil::rotateEulerAngles(gfx::Transform* transform, double eulerX, double eulerY, double eulerZ) |
+{ |
+ // TODO (shawnsingh): make this implementation faster and more accurate by |
+ // hard-coding each matrix instead of calling rotateAxisAngle(). |
+ gfx::Transform rotationAboutX; |
+ gfx::Transform rotationAboutY; |
+ gfx::Transform rotationAboutZ; |
+ |
+ MathUtil::rotateAxisAngle(&rotationAboutX, 1, 0, 0, eulerX); |
+ MathUtil::rotateAxisAngle(&rotationAboutY, 0, 1, 0, eulerY); |
+ MathUtil::rotateAxisAngle(&rotationAboutZ, 0, 0, 1, eulerZ); |
+ |
+ gfx::Transform composite = rotationAboutZ * rotationAboutY * rotationAboutX; |
+ transform->PreconcatTransform(composite); |
+} |
+ |
+void MathUtil::rotateAxisAngle(gfx::Transform* transform, double i, double j, double k, double degrees) |
+{ |
+ // TODO (shawnsingh): fix gfx::Transform API to receive vector instead of |
+ // point for the axis. |
+ gfx::Point3F axis(i, j, k); |
+ transform->PreconcatRotateAbout(axis, degrees); |
+} |
+ |
+gfx::Transform MathUtil::inverse(const gfx::Transform& transform) |
+{ |
+ gfx::Transform result; |
+ bool invertedSuccessfully = transform.GetInverse(&result); |
+ |
+ if (invertedSuccessfully) |
+ return result; |
+ |
+ // If transform was un-invertible, then just return identity. |
+ return gfx::Transform(); |
+} |
+ |
+gfx::Transform MathUtil::to2dTransform(const gfx::Transform& transform) |
+{ |
+ gfx::Transform result = transform; |
+ SkMatrix44& matrix = result.matrix(); |
+ matrix.setDouble(0, 2, 0); |
+ matrix.setDouble(1, 2, 0); |
+ matrix.setDouble(2, 2, 1); |
+ matrix.setDouble(3, 2, 0); |
+ |
+ matrix.setDouble(2, 0, 0); |
+ matrix.setDouble(2, 1, 0); |
+ matrix.setDouble(2, 3, 0); |
+ |
+ return result; |
+} |
+ |
+gfx::Transform MathUtil::createGfxTransform(double m11, double m12, double m13, double m14, |
+ double m21, double m22, double m23, double m24, |
+ double m31, double m32, double m33, double m34, |
+ double m41, double m42, double m43, double m44) |
+{ |
+ gfx::Transform result; |
+ SkMatrix44& matrix = result.matrix(); |
+ |
+ // Initialize column 1 |
+ matrix.setDouble(0, 0, m11); |
+ matrix.setDouble(1, 0, m12); |
+ matrix.setDouble(2, 0, m13); |
+ matrix.setDouble(3, 0, m14); |
+ |
+ // Initialize column 2 |
+ matrix.setDouble(0, 1, m21); |
+ matrix.setDouble(1, 1, m22); |
+ matrix.setDouble(2, 1, m23); |
+ matrix.setDouble(3, 1, m24); |
+ |
+ // Initialize column 3 |
+ matrix.setDouble(0, 2, m31); |
+ matrix.setDouble(1, 2, m32); |
+ matrix.setDouble(2, 2, m33); |
+ matrix.setDouble(3, 2, m34); |
+ |
+ // Initialize column 4 |
+ matrix.setDouble(0, 3, m41); |
+ matrix.setDouble(1, 3, m42); |
+ matrix.setDouble(2, 3, m43); |
+ matrix.setDouble(3, 3, m44); |
+ |
+ return result; |
+} |
+ |
+gfx::Transform MathUtil::createGfxTransform(double a, double b, double c, |
+ double d, double e, double f) |
+{ |
+ gfx::Transform result; |
+ SkMatrix44& matrix = result.matrix(); |
+ matrix.setDouble(0, 0, a); |
+ matrix.setDouble(1, 0, b); |
+ matrix.setDouble(0, 1, c); |
+ matrix.setDouble(1, 1, d); |
+ matrix.setDouble(0, 3, e); |
+ matrix.setDouble(1, 3, f); |
+ |
+ return result; |
+} |
+ |
+gfx::Transform operator*(const gfx::Transform& A, const gfx::Transform& B) |
+{ |
+ // Compute A * B. |
+ gfx::Transform result = A; |
+ result.PreconcatTransform(B); |
+ return result; |
+} |
+ |
} // namespace cc |