18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 Torch Mobile, Inc.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "TransformationMatrix.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
30ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "AffineTransform.h"
318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "FloatPoint3D.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatRect.h"
33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "FloatQuad.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "IntRect.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include <wtf/Assertions.h>
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/MathExtras.h>
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Supporting Math Functions
438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// This is a set of function from various places (attributed inline) to do things like
458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// inversion and decomposition of a 4x4 matrix. They are used throughout the code
468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Adapted from Matrix Inversion by Richard Carling, Graphics Gems <http://tog.acm.org/GraphicsGems/index.html>.
508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// EULA: The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code
528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// as your own and resell it. Using the code is permitted in any program, product, or library, non-commercial
538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// or commercial. Giving credit is not required, though is a nice gesture. The code comes as-is, and if there
548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// are any flaws or problems with any Gems code, nobody involved with Gems - authors, editors, publishers, or
558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes
568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// with no guarantee.
578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// A clarification about the storage of matrix elements
5921939df44de1705786c545cd1bf519d47250322dBen Murdoch//
602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// This class uses a 2 dimensional array internally to store the elements of the matrix.  The first index into
612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// the array refers to the column that the element lies in; the second index refers to the row.
6221939df44de1705786c545cd1bf519d47250322dBen Murdoch//
632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// In other words, this is the layout of the matrix:
642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block//
652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// | m_matrix[0][0] m_matrix[1][0] m_matrix[2][0] m_matrix[3][0] |
662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// | m_matrix[0][1] m_matrix[1][1] m_matrix[2][1] m_matrix[3][1] |
672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// | m_matrix[0][2] m_matrix[1][2] m_matrix[2][2] m_matrix[3][2] |
682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// | m_matrix[0][3] m_matrix[1][3] m_matrix[2][3] m_matrix[3][3] |
6921939df44de1705786c545cd1bf519d47250322dBen Murdoch
708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiantypedef double Vector4[4];
718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiantypedef double Vector3[3];
728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianconst double SMALL_NUMBER = 1.e-8;
748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// inverse(original_matrix, inverse_matrix)
768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// calculate the inverse of a 4x4 matrix
788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// -1
808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// A  = ___1__ adjoint A
818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//       det A
828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//  double = determinant2x2(double a, double b, double c, double d)
848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//  calculate the determinant of a 2x2 matrix.
868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double determinant2x2(double a, double b, double c, double d)
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return a * d - b * c;
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//  double = determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3)
938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//  Calculate the determinant of a 3x3 matrix
958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//  in the form
968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//      | a1,  b1,  c1 |
988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//      | a2,  b2,  c2 |
998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//      | a3,  b3,  c3 |
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double determinant3x3(double a1, double a2, double a3, double b1, double b2, double b3, double c1, double c2, double c3)
1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return a1 * determinant2x2(b2, b3, c2, c3)
1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian         - b1 * determinant2x2(a2, a3, c2, c3)
1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian         + c1 * determinant2x2(a2, a3, b2, b3);
1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//  double = determinant4x4(matrix)
1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//  calculate the determinant of a 4x4 matrix.
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double determinant4x4(const TransformationMatrix::Matrix4& m)
1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Assign to individual variable names to aid selecting
1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // correct elements
1168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a1 = m[0][0];
1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b1 = m[0][1];
1198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c1 = m[0][2];
1208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d1 = m[0][3];
1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a2 = m[1][0];
1238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b2 = m[1][1];
1248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c2 = m[1][2];
1258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d2 = m[1][3];
1268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a3 = m[2][0];
1288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b3 = m[2][1];
1298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c3 = m[2][2];
1308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d3 = m[2][3];
1318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a4 = m[3][0];
1338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b4 = m[3][1];
1348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c4 = m[3][2];
1358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d4 = m[3][3];
1368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return a1 * determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)
1388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian         - b1 * determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)
1398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian         + c1 * determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)
1408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian         - d1 * determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
1418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// adjoint( original_matrix, inverse_matrix )
1448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
1458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//   calculate the adjoint of a 4x4 matrix
1468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
1478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//    Let  a   denote the minor determinant of matrix A obtained by
1488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//         ij
1498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
1508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//    deleting the ith row and jth column from A.
1518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
1528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//                  i+j
1538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//   Let  b   = (-1)    a
1548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//        ij            ji
1558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
1568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//  The matrix B = (b  ) is the adjoint of A
1578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//                   ij
1588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void adjoint(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Matrix4& result)
1608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Assign to individual variable names to aid
1628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // selecting correct values
1638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a1 = matrix[0][0];
1648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b1 = matrix[0][1];
1658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c1 = matrix[0][2];
1668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d1 = matrix[0][3];
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a2 = matrix[1][0];
1698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b2 = matrix[1][1];
1708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c2 = matrix[1][2];
1718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d2 = matrix[1][3];
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a3 = matrix[2][0];
1748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b3 = matrix[2][1];
1758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c3 = matrix[2][2];
1768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d3 = matrix[2][3];
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double a4 = matrix[3][0];
1798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double b4 = matrix[3][1];
1808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double c4 = matrix[3][2];
1818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double d4 = matrix[3][3];
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Row column labeling reversed since we transpose rows & columns
1848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[0][0]  =   determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
1858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[1][0]  = - determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
1868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[2][0]  =   determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
1878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[3][0]  = - determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
1888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[0][1]  = - determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
1908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[1][1]  =   determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
1918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[2][1]  = - determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
1928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[3][1]  =   determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
1938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[0][2]  =   determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
1958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[1][2]  = - determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[2][2]  =   determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
1978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[3][2]  = - determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
1988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[0][3]  = - determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
2008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[1][3]  =   determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[2][3]  = - determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
2028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[3][3]  =   determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
2038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Returns false if the matrix is not invertible
2068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic bool inverse(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Matrix4& result)
2078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Calculate the adjoint matrix
2098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    adjoint(matrix, result);
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Calculate the 4x4 determinant
2128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // If the determinant is zero,
2138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // then the inverse matrix is not unique.
2148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double det = determinant4x4(matrix);
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (fabs(det) < SMALL_NUMBER)
2178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return false;
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Scale the adjoint matrix to get the inverse
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    for (int i = 0; i < 4; i++)
2228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        for (int j = 0; j < 4; j++)
2238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            result[i][j] = result[i][j] / det;
2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return true;
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// End of code adapted from Matrix Inversion by Richard Carling
2298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Perform a decomposition on the passed matrix, return false if unsuccessful
2318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// From Graphics Gems: unmatrix.c
2328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Transpose rotation portion of matrix a, return b
2348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void transposeMatrix4(const TransformationMatrix::Matrix4& a, TransformationMatrix::Matrix4& b)
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    for (int i = 0; i < 4; i++)
2378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        for (int j = 0; j < 4; j++)
2388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            b[i][j] = a[j][i];
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Multiply a homogeneous point by a matrix and return the transformed point
2428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void v4MulPointByMatrix(const Vector4 p, const TransformationMatrix::Matrix4& m, Vector4 result)
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[0] = (p[0] * m[0][0]) + (p[1] * m[1][0]) +
2458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                (p[2] * m[2][0]) + (p[3] * m[3][0]);
2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[1] = (p[0] * m[0][1]) + (p[1] * m[1][1]) +
2478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                (p[2] * m[2][1]) + (p[3] * m[3][1]);
2488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[2] = (p[0] * m[0][2]) + (p[1] * m[1][2]) +
2498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                (p[2] * m[2][2]) + (p[3] * m[3][2]);
2508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[3] = (p[0] * m[0][3]) + (p[1] * m[1][3]) +
2518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                (p[2] * m[2][3]) + (p[3] * m[3][3]);
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double v3Length(Vector3 a)
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return sqrt((a[0] * a[0]) + (a[1] * a[1]) + (a[2] * a[2]));
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void v3Scale(Vector3 v, double desiredLength)
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double len = v3Length(v);
2628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (len != 0) {
2638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double l = desiredLength / len;
2648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        v[0] *= l;
2658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        v[1] *= l;
2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        v[2] *= l;
2678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic double v3Dot(const Vector3 a, const Vector3 b)
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
2738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Make a linear combination of two vectors and return the result.
2768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// result = (a * ascl) + (b * bscl)
2778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void v3Combine(const Vector3 a, const Vector3 b, Vector3 result, double ascl, double bscl)
2788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[0] = (ascl * a[0]) + (bscl * b[0]);
2808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[1] = (ascl * a[1]) + (bscl * b[1]);
2818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[2] = (ascl * a[2]) + (bscl * b[2]);
2828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Return the cross product result = a cross b */
2858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void v3Cross(const Vector3 a, const Vector3 b, Vector3 result)
2868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[0] = (a[1] * b[2]) - (a[2] * b[1]);
2888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[1] = (a[2] * b[0]) - (a[0] * b[2]);
2898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result[2] = (a[0] * b[1]) - (a[1] * b[0]);
2908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic bool decompose(const TransformationMatrix::Matrix4& mat, TransformationMatrix::DecomposedType& result)
2938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix::Matrix4 localMatrix;
2958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    memcpy(localMatrix, mat, sizeof(TransformationMatrix::Matrix4));
2968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Normalize the matrix.
2988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (localMatrix[3][3] == 0)
2998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return false;
3008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    int i, j;
3028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    for (i = 0; i < 4; i++)
3038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        for (j = 0; j < 4; j++)
3048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            localMatrix[i][j] /= localMatrix[3][3];
3058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // perspectiveMatrix is used to solve for perspective, but it also provides
3078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // an easy way to test for singularity of the upper 3x3 component.
3088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix::Matrix4 perspectiveMatrix;
3098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    memcpy(perspectiveMatrix, localMatrix, sizeof(TransformationMatrix::Matrix4));
3108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    for (i = 0; i < 3; i++)
3118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        perspectiveMatrix[i][3] = 0;
3128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    perspectiveMatrix[3][3] = 1;
3138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (determinant4x4(perspectiveMatrix) == 0)
3158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return false;
3168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // First, isolate perspective.  This is the messiest.
3188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (localMatrix[0][3] != 0 || localMatrix[1][3] != 0 || localMatrix[2][3] != 0) {
3198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // rightHandSide is the right hand side of the equation.
3208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        Vector4 rightHandSide;
3218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        rightHandSide[0] = localMatrix[0][3];
3228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        rightHandSide[1] = localMatrix[1][3];
3238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        rightHandSide[2] = localMatrix[2][3];
3248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        rightHandSide[3] = localMatrix[3][3];
3258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // Solve the equation by inverting perspectiveMatrix and multiplying
3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // rightHandSide by the inverse.  (This is the easiest way, not
3288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // necessarily the best.)
3298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        TransformationMatrix::Matrix4 inversePerspectiveMatrix, transposedInversePerspectiveMatrix;
3308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        inverse(perspectiveMatrix, inversePerspectiveMatrix);
3318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        transposeMatrix4(inversePerspectiveMatrix, transposedInversePerspectiveMatrix);
3328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        Vector4 perspectivePoint;
3348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        v4MulPointByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspectivePoint);
3358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        result.perspectiveX = perspectivePoint[0];
3378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        result.perspectiveY = perspectivePoint[1];
3388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        result.perspectiveZ = perspectivePoint[2];
3398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        result.perspectiveW = perspectivePoint[3];
3408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // Clear the perspective partition
3428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        localMatrix[0][3] = localMatrix[1][3] = localMatrix[2][3] = 0;
3438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        localMatrix[3][3] = 1;
3448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
3458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // No perspective.
3468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        result.perspectiveX = result.perspectiveY = result.perspectiveZ = 0;
3478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        result.perspectiveW = 1;
3488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
3498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Next take care of translation (easy).
3518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.translateX = localMatrix[3][0];
3528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    localMatrix[3][0] = 0;
3538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.translateY = localMatrix[3][1];
3548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    localMatrix[3][1] = 0;
3558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.translateZ = localMatrix[3][2];
3568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    localMatrix[3][2] = 0;
3578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Vector4 type and functions need to be added to the common set.
3598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Vector3 row[3], pdum3;
3608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Now get scale and shear.
3628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    for (i = 0; i < 3; i++) {
3638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        row[i][0] = localMatrix[i][0];
3648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        row[i][1] = localMatrix[i][1];
3658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        row[i][2] = localMatrix[i][2];
3668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
3678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Compute X scale factor and normalize first row.
3698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.scaleX = v3Length(row[0]);
3708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    v3Scale(row[0], 1.0);
3718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Compute XY shear factor and make 2nd row orthogonal to 1st.
3738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.skewXY = v3Dot(row[0], row[1]);
3748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    v3Combine(row[1], row[0], row[1], 1.0, -result.skewXY);
3758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Now, compute Y scale and normalize 2nd row.
3778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.scaleY = v3Length(row[1]);
3788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    v3Scale(row[1], 1.0);
3798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.skewXY /= result.scaleY;
3808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Compute XZ and YZ shears, orthogonalize 3rd row.
3828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.skewXZ = v3Dot(row[0], row[2]);
3838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    v3Combine(row[2], row[0], row[2], 1.0, -result.skewXZ);
3848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.skewYZ = v3Dot(row[1], row[2]);
3858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    v3Combine(row[2], row[1], row[2], 1.0, -result.skewYZ);
3868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Next, get Z scale and normalize 3rd row.
3888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.scaleZ = v3Length(row[2]);
3898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    v3Scale(row[2], 1.0);
3908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.skewXZ /= result.scaleZ;
3918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.skewYZ /= result.scaleZ;
3928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
3938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // At this point, the matrix (in rows[]) is orthonormal.
3948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Check for a coordinate system flip.  If the determinant
3958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // is -1, then negate the matrix and the scaling factors.
3968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    v3Cross(row[1], row[2], pdum3);
3978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (v3Dot(row[0], pdum3) < 0) {
3988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        for (i = 0; i < 3; i++) {
3998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            result.scaleX *= -1;
4008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            row[i][0] *= -1;
4018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            row[i][1] *= -1;
4028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            row[i][2] *= -1;
4038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
4048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
4058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Now, get the rotations out, as described in the gem.
4078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // FIXME - Add the ability to return either quaternions (which are
4098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // easier to recompose with) or Euler angles (rx, ry, rz), which
4108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // are easier for authors to deal with. The latter will only be useful
4118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // when we fix https://bugs.webkit.org/show_bug.cgi?id=23799, so I
4128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // will leave the Euler angle code here for now.
4138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // ret.rotateY = asin(-row[0][2]);
4158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // if (cos(ret.rotateY) != 0) {
4168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    //     ret.rotateX = atan2(row[1][2], row[2][2]);
4178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    //     ret.rotateZ = atan2(row[0][1], row[0][0]);
4188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // } else {
4198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    //     ret.rotateX = atan2(-row[2][0], row[1][1]);
4208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    //     ret.rotateZ = 0;
4218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // }
4228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double s, t, x, y, z, w;
4248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    t = row[0][0] + row[1][1] + row[2][2] + 1.0;
4268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (t > 1e-4) {
4288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        s = 0.5 / sqrt(t);
4298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        w = 0.25 / s;
4308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        x = (row[2][1] - row[1][2]) * s;
4318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        y = (row[0][2] - row[2][0]) * s;
4328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        z = (row[1][0] - row[0][1]) * s;
4338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) {
4348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        s = sqrt (1.0 + row[0][0] - row[1][1] - row[2][2]) * 2.0; // S=4*qx
4358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        x = 0.25 * s;
4368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        y = (row[0][1] + row[1][0]) / s;
4378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        z = (row[0][2] + row[2][0]) / s;
4388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        w = (row[2][1] - row[1][2]) / s;
4398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else if (row[1][1] > row[2][2]) {
4408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        s = sqrt (1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; // S=4*qy
4418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        x = (row[0][1] + row[1][0]) / s;
4428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        y = 0.25 * s;
4438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        z = (row[1][2] + row[2][1]) / s;
4448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        w = (row[0][2] - row[2][0]) / s;
4458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
4468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        s = sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; // S=4*qz
4478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        x = (row[0][2] + row[2][0]) / s;
4488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        y = (row[1][2] + row[2][1]) / s;
4498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        z = 0.25 * s;
4508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        w = (row[1][0] - row[0][1]) / s;
4518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
4528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.quaternionX = x;
4548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.quaternionY = y;
4558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.quaternionZ = z;
4568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.quaternionW = w;
4578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return true;
4598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
4608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Perform a spherical linear interpolation between the two
4628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// passed quaternions with 0 <= t <= 1
4638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void slerp(double qa[4], const double qb[4], double t)
4648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
4658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double ax, ay, az, aw;
4668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double bx, by, bz, bw;
4678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double cx, cy, cz, cw;
4688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double angle;
4698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double th, invth, scale, invscale;
4708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ax = qa[0]; ay = qa[1]; az = qa[2]; aw = qa[3];
4728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bx = qb[0]; by = qb[1]; bz = qb[2]; bw = qb[3];
4738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    angle = ax * bx + ay * by + az * bz + aw * bw;
4758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (angle < 0.0) {
4778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ax = -ax; ay = -ay;
4788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        az = -az; aw = -aw;
4798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        angle = -angle;
4808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
4818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (angle + 1.0 > .05) {
4838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (1.0 - angle >= .05) {
4848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            th = acos (angle);
4858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            invth = 1.0 / sin (th);
4868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            scale = sin (th * (1.0 - t)) * invth;
4878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            invscale = sin (th * t) * invth;
4888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        } else {
4898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            scale = 1.0 - t;
4908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            invscale = t;
4918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
4928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
4938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        bx = -ay;
4948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        by = ax;
4958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        bz = -aw;
4968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        bw = az;
4978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        scale = sin(piDouble * (.5 - t));
4988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        invscale = sin (piDouble * t);
4998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
5008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    cx = ax * scale + bx * invscale;
5028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    cy = ay * scale + by * invscale;
5038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    cz = az * scale + bz * invscale;
5048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    cw = aw * scale + bw * invscale;
5058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    qa[0] = cx; qa[1] = cy; qa[2] = cz; qa[3] = cw;
5078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
5088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// End of Supporting Math Functions
5108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::scale(double s)
5128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
5138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return scaleNonUniform(s, s);
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
516635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectTransformationMatrix& TransformationMatrix::rotateFromVector(double x, double y)
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return rotate(rad2deg(atan2(y, x)));
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
521635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectTransformationMatrix& TransformationMatrix::flipX()
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return scaleNonUniform(-1.0f, 1.0f);
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
526635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectTransformationMatrix& TransformationMatrix::flipY()
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return scaleNonUniform(1.0f, -1.0f);
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatPoint TransformationMatrix::projectPoint(const FloatPoint& p) const
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // This is basically raytracing. We have a point in the destination
5348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // plane with z=0, and we cast a ray parallel to the z-axis from that
5358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // point to find the z-position at which it intersects the z=0 plane
5368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // with the transform applied. Once we have that point we apply the
5378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // inverse transform to find the corresponding point in the source
5388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // space.
5398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    //
5408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Given a plane with normal Pn, and a ray starting at point R0 and
5418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // with direction defined by the vector Rd, we can find the
5428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // intersection point as a distance d from R0 in units of Rd by:
5438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    //
5448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // d = -dot (Pn', R0) / dot (Pn', Rd)
5458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double x = p.x();
5478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double y = p.y();
5488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double z = -(m13() * x + m23() * y + m43()) / m33();
5498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double outX = x * m11() + y * m21() + z * m31() + m41();
5518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double outY = x * m12() + y * m22() + z * m32() + m42();
5528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double w = x * m14() + y * m24() + z * m34() + m44();
5548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (w != 1 && w != 0) {
5558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        outX /= w;
5568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        outY /= w;
5578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
5588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return FloatPoint(static_cast<float>(outX), static_cast<float>(outY));
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatQuad TransformationMatrix::projectQuad(const FloatQuad& q) const
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FloatQuad projectedQuad;
5658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    projectedQuad.setP1(projectPoint(q.p1()));
5668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    projectedQuad.setP2(projectPoint(q.p2()));
5678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    projectedQuad.setP3(projectPoint(q.p3()));
5688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    projectedQuad.setP4(projectPoint(q.p4()));
5698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return projectedQuad;
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatPoint TransformationMatrix::mapPoint(const FloatPoint& p) const
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (isIdentityOrTranslation())
5755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return FloatPoint(p.x() + static_cast<float>(m_matrix[3][0]), p.y() + static_cast<float>(m_matrix[3][1]));
5765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double x, y;
5788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    multVecMatrix(p.x(), p.y(), x, y);
5798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return FloatPoint(static_cast<float>(x), static_cast<float>(y));
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatPoint3D TransformationMatrix::mapPoint(const FloatPoint3D& p) const
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (isIdentityOrTranslation())
5855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return FloatPoint3D(p.x() + static_cast<float>(m_matrix[3][0]),
5865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                            p.y() + static_cast<float>(m_matrix[3][1]),
5875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                            p.z() + static_cast<float>(m_matrix[3][2]));
5885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double x, y, z;
5908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    multVecMatrix(p.x(), p.y(), p.z(), x, y, z);
5918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return FloatPoint3D(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianIntRect TransformationMatrix::mapRect(const IntRect &rect) const
5958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
5968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return enclosingIntRect(mapRect(FloatRect(rect)));
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatRect TransformationMatrix::mapRect(const FloatRect& r) const
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (isIdentityOrTranslation()) {
6025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        FloatRect mappedRect(r);
6035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        mappedRect.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
6045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return mappedRect;
6055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
6065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
6078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FloatQuad resultQuad = mapQuad(FloatQuad(r));
6088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return resultQuad.boundingBox();
6098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianFloatQuad TransformationMatrix::mapQuad(const FloatQuad& q) const
6128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
6135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (isIdentityOrTranslation()) {
6145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        FloatQuad mappedQuad(q);
6155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        mappedQuad.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
6165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return mappedQuad;
6175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
6185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
6198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FloatQuad result;
6208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.setP1(mapPoint(q.p1()));
6218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.setP2(mapPoint(q.p2()));
6228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.setP3(mapPoint(q.p3()));
6238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    result.setP4(mapPoint(q.p4()));
6248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return result;
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::scaleNonUniform(double sx, double sy)
628635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
6298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix mat;
6308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][0] = sx;
6318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][1] = sy;
6328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    multiply(mat);
6348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
635635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
636635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
6378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::scale3d(double sx, double sy, double sz)
6388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
6398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix mat;
6408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][0] = sx;
6418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][1] = sy;
6428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][2] = sz;
6438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    multiply(mat);
6458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
6468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
6478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double z, double angle)
6498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
6508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // angles are in degrees. Switch to radians
6518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    angle = deg2rad(angle);
6528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    angle /= 2.0f;
6548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double sinA = sin(angle);
6558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double cosA = cos(angle);
6568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double sinA2 = sinA * sinA;
6578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // normalize
6598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double length = sqrt(x * x + y * y + z * z);
6608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (length == 0) {
6618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // bad vector, just use something reasonable
6628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        x = 0;
6638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        y = 0;
6648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        z = 1;
6658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else if (length != 1) {
6668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        x /= length;
6678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        y /= length;
6688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        z /= length;
6698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
6708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix mat;
6728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // optimize case where axis is along major axis
6748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (x == 1.0f && y == 0.0f && z == 0.0f) {
6758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][0] = 1.0f;
6768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][1] = 0.0f;
6778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][2] = 0.0f;
6788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][0] = 0.0f;
6798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2;
6808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][2] = 2.0f * sinA * cosA;
6818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][0] = 0.0f;
6828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][1] = -2.0f * sinA * cosA;
6838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2;
6848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
6858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
6868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[3][3] = 1.0f;
6878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else if (x == 0.0f && y == 1.0f && z == 0.0f) {
6888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2;
6898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][1] = 0.0f;
6908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][2] = -2.0f * sinA * cosA;
6918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][0] = 0.0f;
6928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][1] = 1.0f;
6938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][2] = 0.0f;
6948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][0] = 2.0f * sinA * cosA;
6958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][1] = 0.0f;
6968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2;
6978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
6988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
6998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[3][3] = 1.0f;
7008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else if (x == 0.0f && y == 0.0f && z == 1.0f) {
7018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2;
7028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][1] = 2.0f * sinA * cosA;
7038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][2] = 0.0f;
7048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][0] = -2.0f * sinA * cosA;
7058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2;
7068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][2] = 0.0f;
7078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][0] = 0.0f;
7088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][1] = 0.0f;
7098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][2] = 1.0f;
7108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
7118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
7128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[3][3] = 1.0f;
7138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
7148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double x2 = x*x;
7158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double y2 = y*y;
7168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double z2 = z*z;
7178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][0] = 1.0f - 2.0f * (y2 + z2) * sinA2;
7198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][1] = 2.0f * (x * y * sinA2 + z * sinA * cosA);
7208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][2] = 2.0f * (x * z * sinA2 - y * sinA * cosA);
7218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][0] = 2.0f * (y * x * sinA2 - z * sinA * cosA);
7228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][1] = 1.0f - 2.0f * (z2 + x2) * sinA2;
7238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[1][2] = 2.0f * (y * z * sinA2 + x * sinA * cosA);
7248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][0] = 2.0f * (z * x * sinA2 + y * sinA * cosA);
7258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][1] = 2.0f * (z * y * sinA2 - x * sinA * cosA);
7268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][2] = 1.0f - 2.0f * (x2 + y2) * sinA2;
7278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
7288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
7298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[3][3] = 1.0f;
7308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
7312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    multiply(mat);
7328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
7338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
7348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, double rz)
7368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
7378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // angles are in degrees. Switch to radians
7388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    rx = deg2rad(rx);
7398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ry = deg2rad(ry);
7408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    rz = deg2rad(rz);
7418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix mat;
7438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    rz /= 2.0f;
7458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double sinA = sin(rz);
7468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double cosA = cos(rz);
7478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double sinA2 = sinA * sinA;
7488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2;
7508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][1] = 2.0f * sinA * cosA;
7518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][2] = 0.0f;
7528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][0] = -2.0f * sinA * cosA;
7538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2;
7548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][2] = 0.0f;
7558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][0] = 0.0f;
7568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][1] = 0.0f;
7578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][2] = 1.0f;
7588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
7598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
7608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[3][3] = 1.0f;
7618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix rmat(mat);
7638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ry /= 2.0f;
7658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    sinA = sin(ry);
7668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    cosA = cos(ry);
7678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    sinA2 = sinA * sinA;
7688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2;
7708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][1] = 0.0f;
7718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][2] = -2.0f * sinA * cosA;
7728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][0] = 0.0f;
7738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][1] = 1.0f;
7748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][2] = 0.0f;
7758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][0] = 2.0f * sinA * cosA;
7768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][1] = 0.0f;
7778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2;
7788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
7798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
7808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[3][3] = 1.0f;
7818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    rmat.multiply(mat);
7838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    rx /= 2.0f;
7858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    sinA = sin(rx);
7868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    cosA = cos(rx);
7878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    sinA2 = sinA * sinA;
7888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][0] = 1.0f;
7908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][1] = 0.0f;
7918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][2] = 0.0f;
7928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][0] = 0.0f;
7938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2;
7948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][2] = 2.0f * sinA * cosA;
7958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][0] = 0.0f;
7968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][1] = -2.0f * sinA * cosA;
7978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2;
7988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
7998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
8008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[3][3] = 1.0f;
8018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    rmat.multiply(mat);
8038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    multiply(rmat);
8058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
8068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::translate(double tx, double ty)
8098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
810353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed    m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0];
811353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed    m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1];
812353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed    m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2];
813353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed    m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3];
8148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
8158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::translate3d(double tx, double ty, double tz)
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
819353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed    m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0] + tz * m_matrix[2][0];
820353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed    m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1] + tz * m_matrix[2][1];
821353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed    m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2] + tz * m_matrix[2][2];
822353e1e16ed060c0ea11f2dea6dea8b565ac71533Mike Reed    m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3] + tz * m_matrix[2][3];
8238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
8248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::translateRight(double tx, double ty)
8278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
8288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (tx != 0) {
8298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[0][0] +=  m_matrix[0][3] * tx;
8308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[1][0] +=  m_matrix[1][3] * tx;
8318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[2][0] +=  m_matrix[2][3] * tx;
8328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[3][0] +=  m_matrix[3][3] * tx;
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (ty != 0) {
8368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[0][1] +=  m_matrix[0][3] * ty;
8378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[1][1] +=  m_matrix[1][3] * ty;
8388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[2][1] +=  m_matrix[2][3] * ty;
8398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[3][1] +=  m_matrix[3][3] * ty;
8408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
8438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::translateRight3d(double tx, double ty, double tz)
8468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
8478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    translateRight(tx, ty);
8488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (tz != 0) {
8498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[0][2] +=  m_matrix[0][3] * tz;
8508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[1][2] +=  m_matrix[1][3] * tz;
8518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[2][2] +=  m_matrix[2][3] * tz;
8528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_matrix[3][2] +=  m_matrix[3][3] * tz;
8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
8568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::skew(double sx, double sy)
8598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
8608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // angles are in degrees. Switch to radians
8618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    sx = deg2rad(sx);
8628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    sy = deg2rad(sy);
8638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix mat;
8658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[0][1] = tan(sy); // note that the y shear goes in the first row
8668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    mat.m_matrix[1][0] = tan(sx); // and the x shear in the second row
8678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    multiply(mat);
8698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
8708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix& TransformationMatrix::applyPerspective(double p)
8738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
8748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix mat;
8758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (p != 0)
8768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        mat.m_matrix[2][3] = -1/p;
8778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    multiply(mat);
8798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
8808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
8818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochTransformationMatrix TransformationMatrix::rectToRect(const FloatRect& from, const FloatRect& to)
8830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
8840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(!from.isEmpty());
8850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return TransformationMatrix(to.width() / from.width(),
8860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                0, 0,
8870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                to.height() / from.height(),
8880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                to.x() - from.x(),
8890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                to.y() - from.y());
8900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
8910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
8938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// *this = mat * *this
8948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian//
8952fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockTransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& mat)
8968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
8978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Matrix4 tmp;
8988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[0][0] = (mat.m_matrix[0][0] * m_matrix[0][0] + mat.m_matrix[0][1] * m_matrix[1][0]
9008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[0][2] * m_matrix[2][0] + mat.m_matrix[0][3] * m_matrix[3][0]);
9018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[0][1] = (mat.m_matrix[0][0] * m_matrix[0][1] + mat.m_matrix[0][1] * m_matrix[1][1]
9028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[0][2] * m_matrix[2][1] + mat.m_matrix[0][3] * m_matrix[3][1]);
9038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[0][2] = (mat.m_matrix[0][0] * m_matrix[0][2] + mat.m_matrix[0][1] * m_matrix[1][2]
9048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[0][2] * m_matrix[2][2] + mat.m_matrix[0][3] * m_matrix[3][2]);
9058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[0][3] = (mat.m_matrix[0][0] * m_matrix[0][3] + mat.m_matrix[0][1] * m_matrix[1][3]
9068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[0][2] * m_matrix[2][3] + mat.m_matrix[0][3] * m_matrix[3][3]);
9078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[1][0] = (mat.m_matrix[1][0] * m_matrix[0][0] + mat.m_matrix[1][1] * m_matrix[1][0]
9098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[1][2] * m_matrix[2][0] + mat.m_matrix[1][3] * m_matrix[3][0]);
9108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[1][1] = (mat.m_matrix[1][0] * m_matrix[0][1] + mat.m_matrix[1][1] * m_matrix[1][1]
9118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[1][2] * m_matrix[2][1] + mat.m_matrix[1][3] * m_matrix[3][1]);
9128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[1][2] = (mat.m_matrix[1][0] * m_matrix[0][2] + mat.m_matrix[1][1] * m_matrix[1][2]
9138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[1][2] * m_matrix[2][2] + mat.m_matrix[1][3] * m_matrix[3][2]);
9148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[1][3] = (mat.m_matrix[1][0] * m_matrix[0][3] + mat.m_matrix[1][1] * m_matrix[1][3]
9158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[1][2] * m_matrix[2][3] + mat.m_matrix[1][3] * m_matrix[3][3]);
9168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[2][0] = (mat.m_matrix[2][0] * m_matrix[0][0] + mat.m_matrix[2][1] * m_matrix[1][0]
9188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[2][2] * m_matrix[2][0] + mat.m_matrix[2][3] * m_matrix[3][0]);
9198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[2][1] = (mat.m_matrix[2][0] * m_matrix[0][1] + mat.m_matrix[2][1] * m_matrix[1][1]
9208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[2][2] * m_matrix[2][1] + mat.m_matrix[2][3] * m_matrix[3][1]);
9218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[2][2] = (mat.m_matrix[2][0] * m_matrix[0][2] + mat.m_matrix[2][1] * m_matrix[1][2]
9228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[2][2] * m_matrix[2][2] + mat.m_matrix[2][3] * m_matrix[3][2]);
9238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[2][3] = (mat.m_matrix[2][0] * m_matrix[0][3] + mat.m_matrix[2][1] * m_matrix[1][3]
9248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[2][2] * m_matrix[2][3] + mat.m_matrix[2][3] * m_matrix[3][3]);
9258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[3][0] = (mat.m_matrix[3][0] * m_matrix[0][0] + mat.m_matrix[3][1] * m_matrix[1][0]
9278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[3][2] * m_matrix[2][0] + mat.m_matrix[3][3] * m_matrix[3][0]);
9288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[3][1] = (mat.m_matrix[3][0] * m_matrix[0][1] + mat.m_matrix[3][1] * m_matrix[1][1]
9298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[3][2] * m_matrix[2][1] + mat.m_matrix[3][3] * m_matrix[3][1]);
9308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[3][2] = (mat.m_matrix[3][0] * m_matrix[0][2] + mat.m_matrix[3][1] * m_matrix[1][2]
9318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[3][2] * m_matrix[2][2] + mat.m_matrix[3][3] * m_matrix[3][2]);
9328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    tmp[3][3] = (mat.m_matrix[3][0] * m_matrix[0][3] + mat.m_matrix[3][1] * m_matrix[1][3]
9338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian               + mat.m_matrix[3][2] * m_matrix[2][3] + mat.m_matrix[3][3] * m_matrix[3][3]);
9348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    setMatrix(tmp);
9368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return *this;
9378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
9388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::multVecMatrix(double x, double y, double& resultX, double& resultY) const
9408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
9418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0];
9428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1];
9438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3];
9448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (w != 1 && w != 0) {
9458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        resultX /= w;
9468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        resultY /= w;
9478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
9488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
9498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::multVecMatrix(double x, double y, double z, double& resultX, double& resultY, double& resultZ) const
9518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
9528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0] + z * m_matrix[2][0];
9538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1] + z * m_matrix[2][1];
9548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    resultZ = m_matrix[3][2] + x * m_matrix[0][2] + y * m_matrix[1][2] + z * m_matrix[2][2];
9558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3] + z * m_matrix[2][3];
9568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (w != 1 && w != 0) {
9578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        resultX /= w;
9588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        resultY /= w;
9598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        resultZ /= w;
9608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
9618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
9628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool TransformationMatrix::isInvertible() const
9648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
9655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (isIdentityOrTranslation())
9665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return true;
9675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double det = WebCore::determinant4x4(m_matrix);
9698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (fabs(det) < SMALL_NUMBER)
9718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return false;
9728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return true;
9748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
9758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianTransformationMatrix TransformationMatrix::inverse() const
9778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
9785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (isIdentityOrTranslation()) {
9795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // identity matrix
9805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0)
9815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return TransformationMatrix();
9825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // translation
9845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return TransformationMatrix(1, 0, 0, 0,
9855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                                    0, 1, 0, 0,
9865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                                    0, 0, 1, 0,
9875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                                    -m_matrix[3][0], -m_matrix[3][1], -m_matrix[3][2], 1);
9885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    TransformationMatrix invMat;
9918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool inverted = WebCore::inverse(m_matrix, invMat.m_matrix);
9928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!inverted)
9938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return TransformationMatrix();
9948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return invMat;
9968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
9978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::makeAffine()
9998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
10008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[0][2] = 0;
10018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[0][3] = 0;
10028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[1][2] = 0;
10048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[1][3] = 0;
10058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[2][0] = 0;
10078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[2][1] = 0;
10088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[2][2] = 1;
10098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[2][3] = 0;
10108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[3][2] = 0;
10128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[3][3] = 1;
10138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
10148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockAffineTransform TransformationMatrix::toAffineTransform() const
10168a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{
10178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return AffineTransform(m_matrix[0][0], m_matrix[0][1], m_matrix[1][0],
10188a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                           m_matrix[1][1], m_matrix[3][0], m_matrix[3][1]);
10198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block}
10208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
10218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic inline void blendFloat(double& from, double to, double progress)
10228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
10238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (from != to)
10248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        from = from + (to - from) * progress;
10258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
10268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::blend(const TransformationMatrix& from, double progress)
10288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
10298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (from.isIdentity() && isIdentity())
10308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
10318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // decompose
10338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    DecomposedType fromDecomp;
10348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    DecomposedType toDecomp;
10358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    from.decompose(fromDecomp);
10368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    decompose(toDecomp);
10378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // interpolate
10398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress);
10408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress);
10418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.scaleZ, toDecomp.scaleZ, progress);
10428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.skewXY, toDecomp.skewXY, progress);
10438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.skewXZ, toDecomp.skewXZ, progress);
10448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.skewYZ, toDecomp.skewYZ, progress);
10458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.translateX, toDecomp.translateX, progress);
10468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.translateY, toDecomp.translateY, progress);
10478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.translateZ, toDecomp.translateZ, progress);
10488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.perspectiveX, toDecomp.perspectiveX, progress);
10498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.perspectiveY, toDecomp.perspectiveY, progress);
10508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.perspectiveZ, toDecomp.perspectiveZ, progress);
10518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    blendFloat(fromDecomp.perspectiveW, toDecomp.perspectiveW, progress);
10528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    slerp(&fromDecomp.quaternionX, &toDecomp.quaternionX, progress);
10548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // recompose
10568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    recompose(fromDecomp);
10578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
10588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianbool TransformationMatrix::decompose(DecomposedType& decomp) const
10608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
10618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isIdentity()) {
10628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        memset(&decomp, 0, sizeof(decomp));
10638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        decomp.perspectiveW = 1;
10648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        decomp.scaleX = 1;
10658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        decomp.scaleY = 1;
10668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        decomp.scaleZ = 1;
10678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
10688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!WebCore::decompose(m_matrix, decomp))
10708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return false;
10718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return true;
10728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
10738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TransformationMatrix::recompose(const DecomposedType& decomp)
10758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
10768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    makeIdentity();
10778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // first apply perspective
10798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[0][3] = (float) decomp.perspectiveX;
10808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[1][3] = (float) decomp.perspectiveY;
10818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[2][3] = (float) decomp.perspectiveZ;
10828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_matrix[3][3] = (float) decomp.perspectiveW;
10838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // now translate
10858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    translate3d((float) decomp.translateX, (float) decomp.translateY, (float) decomp.translateZ);
10868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // apply rotation
10888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double xx = decomp.quaternionX * decomp.quaternionX;
10898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double xy = decomp.quaternionX * decomp.quaternionY;
10908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double xz = decomp.quaternionX * decomp.quaternionZ;
10918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double xw = decomp.quaternionX * decomp.quaternionW;
10928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double yy = decomp.quaternionY * decomp.quaternionY;
10938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double yz = decomp.quaternionY * decomp.quaternionZ;
10948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double yw = decomp.quaternionY * decomp.quaternionW;
10958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double zz = decomp.quaternionZ * decomp.quaternionZ;
10968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double zw = decomp.quaternionZ * decomp.quaternionW;
10978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Construct a composite rotation matrix from the quaternion values
10998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix rotationMatrix(1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0,
11008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                           2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0,
11018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                           2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0,
11028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                           0, 0, 0, 1);
11038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    multiply(rotationMatrix);
11058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // now apply skew
11078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (decomp.skewYZ) {
11088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        TransformationMatrix tmp;
11098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        tmp.setM32((float) decomp.skewYZ);
11102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        multiply(tmp);
11118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
11128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (decomp.skewXZ) {
11148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        TransformationMatrix tmp;
11158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        tmp.setM31((float) decomp.skewXZ);
11162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        multiply(tmp);
11178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
11188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (decomp.skewXY) {
11208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        TransformationMatrix tmp;
11218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        tmp.setM21((float) decomp.skewXY);
11222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        multiply(tmp);
11238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
11248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // finally, apply scale
11268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    scale3d((float) decomp.scaleX, (float) decomp.scaleY, (float) decomp.scaleZ);
11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1130