Home | History | Annotate | Download | only in transforms
      1 /*
      2  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
      3  * Copyright (C) 2009 Torch Mobile, Inc.
      4  * Copyright (C) 2013 Google Inc. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "config.h"
     29 #include "core/platform/graphics/transforms/TransformationMatrix.h"
     30 
     31 #include "core/platform/graphics/FloatQuad.h"
     32 #include "core/platform/graphics/FloatRect.h"
     33 #include "core/platform/graphics/IntRect.h"
     34 #include "core/platform/graphics/LayoutRect.h"
     35 #include "core/platform/graphics/skia/SkiaUtils.h"
     36 #include "core/platform/graphics/transforms/AffineTransform.h"
     37 
     38 #include "wtf/Assertions.h"
     39 #include "wtf/MathExtras.h"
     40 
     41 #if CPU(X86_64)
     42 #include <emmintrin.h>
     43 #endif
     44 
     45 using namespace std;
     46 
     47 namespace WebCore {
     48 
     49 //
     50 // Supporting Math Functions
     51 //
     52 // This is a set of function from various places (attributed inline) to do things like
     53 // inversion and decomposition of a 4x4 matrix. They are used throughout the code
     54 //
     55 
     56 //
     57 // Adapted from Matrix Inversion by Richard Carling, Graphics Gems <http://tog.acm.org/GraphicsGems/index.html>.
     58 
     59 // EULA: The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code
     60 // as your own and resell it. Using the code is permitted in any program, product, or library, non-commercial
     61 // or commercial. Giving credit is not required, though is a nice gesture. The code comes as-is, and if there
     62 // are any flaws or problems with any Gems code, nobody involved with Gems - authors, editors, publishers, or
     63 // webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes
     64 // with no guarantee.
     65 
     66 // A clarification about the storage of matrix elements
     67 //
     68 // This class uses a 2 dimensional array internally to store the elements of the matrix.  The first index into
     69 // the array refers to the column that the element lies in; the second index refers to the row.
     70 //
     71 // In other words, this is the layout of the matrix:
     72 //
     73 // | m_matrix[0][0] m_matrix[1][0] m_matrix[2][0] m_matrix[3][0] |
     74 // | m_matrix[0][1] m_matrix[1][1] m_matrix[2][1] m_matrix[3][1] |
     75 // | m_matrix[0][2] m_matrix[1][2] m_matrix[2][2] m_matrix[3][2] |
     76 // | m_matrix[0][3] m_matrix[1][3] m_matrix[2][3] m_matrix[3][3] |
     77 
     78 typedef double Vector4[4];
     79 typedef double Vector3[3];
     80 
     81 const double SMALL_NUMBER = 1.e-8;
     82 
     83 // inverse(original_matrix, inverse_matrix)
     84 //
     85 // calculate the inverse of a 4x4 matrix
     86 //
     87 // -1
     88 // A  = ___1__ adjoint A
     89 //       det A
     90 
     91 //  double = determinant2x2(double a, double b, double c, double d)
     92 //
     93 //  calculate the determinant of a 2x2 matrix.
     94 
     95 static double determinant2x2(double a, double b, double c, double d)
     96 {
     97     return a * d - b * c;
     98 }
     99 
    100 //  double = determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3)
    101 //
    102 //  Calculate the determinant of a 3x3 matrix
    103 //  in the form
    104 //
    105 //      | a1,  b1,  c1 |
    106 //      | a2,  b2,  c2 |
    107 //      | a3,  b3,  c3 |
    108 
    109 static double determinant3x3(double a1, double a2, double a3, double b1, double b2, double b3, double c1, double c2, double c3)
    110 {
    111     return a1 * determinant2x2(b2, b3, c2, c3)
    112          - b1 * determinant2x2(a2, a3, c2, c3)
    113          + c1 * determinant2x2(a2, a3, b2, b3);
    114 }
    115 
    116 //  double = determinant4x4(matrix)
    117 //
    118 //  calculate the determinant of a 4x4 matrix.
    119 
    120 static double determinant4x4(const TransformationMatrix::Matrix4& m)
    121 {
    122     // Assign to individual variable names to aid selecting
    123     // correct elements
    124 
    125     double a1 = m[0][0];
    126     double b1 = m[0][1];
    127     double c1 = m[0][2];
    128     double d1 = m[0][3];
    129 
    130     double a2 = m[1][0];
    131     double b2 = m[1][1];
    132     double c2 = m[1][2];
    133     double d2 = m[1][3];
    134 
    135     double a3 = m[2][0];
    136     double b3 = m[2][1];
    137     double c3 = m[2][2];
    138     double d3 = m[2][3];
    139 
    140     double a4 = m[3][0];
    141     double b4 = m[3][1];
    142     double c4 = m[3][2];
    143     double d4 = m[3][3];
    144 
    145     return a1 * determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)
    146          - b1 * determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)
    147          + c1 * determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)
    148          - d1 * determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
    149 }
    150 
    151 // adjoint( original_matrix, inverse_matrix )
    152 //
    153 //   calculate the adjoint of a 4x4 matrix
    154 //
    155 //    Let  a   denote the minor determinant of matrix A obtained by
    156 //         ij
    157 //
    158 //    deleting the ith row and jth column from A.
    159 //
    160 //                  i+j
    161 //   Let  b   = (-1)    a
    162 //        ij            ji
    163 //
    164 //  The matrix B = (b  ) is the adjoint of A
    165 //                   ij
    166 
    167 static void adjoint(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Matrix4& result)
    168 {
    169     // Assign to individual variable names to aid
    170     // selecting correct values
    171     double a1 = matrix[0][0];
    172     double b1 = matrix[0][1];
    173     double c1 = matrix[0][2];
    174     double d1 = matrix[0][3];
    175 
    176     double a2 = matrix[1][0];
    177     double b2 = matrix[1][1];
    178     double c2 = matrix[1][2];
    179     double d2 = matrix[1][3];
    180 
    181     double a3 = matrix[2][0];
    182     double b3 = matrix[2][1];
    183     double c3 = matrix[2][2];
    184     double d3 = matrix[2][3];
    185 
    186     double a4 = matrix[3][0];
    187     double b4 = matrix[3][1];
    188     double c4 = matrix[3][2];
    189     double d4 = matrix[3][3];
    190 
    191     // Row column labeling reversed since we transpose rows & columns
    192     result[0][0]  =   determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
    193     result[1][0]  = - determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
    194     result[2][0]  =   determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
    195     result[3][0]  = - determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
    196 
    197     result[0][1]  = - determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
    198     result[1][1]  =   determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
    199     result[2][1]  = - determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
    200     result[3][1]  =   determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
    201 
    202     result[0][2]  =   determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
    203     result[1][2]  = - determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
    204     result[2][2]  =   determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
    205     result[3][2]  = - determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
    206 
    207     result[0][3]  = - determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
    208     result[1][3]  =   determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
    209     result[2][3]  = - determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
    210     result[3][3]  =   determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
    211 }
    212 
    213 // Returns false if the matrix is not invertible
    214 static bool inverse(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Matrix4& result)
    215 {
    216     // Calculate the adjoint matrix
    217     adjoint(matrix, result);
    218 
    219     // Calculate the 4x4 determinant
    220     // If the determinant is zero,
    221     // then the inverse matrix is not unique.
    222     double det = determinant4x4(matrix);
    223 
    224     if (fabs(det) < SMALL_NUMBER)
    225         return false;
    226 
    227     // Scale the adjoint matrix to get the inverse
    228 
    229     for (int i = 0; i < 4; i++)
    230         for (int j = 0; j < 4; j++)
    231             result[i][j] = result[i][j] / det;
    232 
    233     return true;
    234 }
    235 
    236 // End of code adapted from Matrix Inversion by Richard Carling
    237 
    238 // Perform a decomposition on the passed matrix, return false if unsuccessful
    239 // From Graphics Gems: unmatrix.c
    240 
    241 // Transpose rotation portion of matrix a, return b
    242 static void transposeMatrix4(const TransformationMatrix::Matrix4& a, TransformationMatrix::Matrix4& b)
    243 {
    244     for (int i = 0; i < 4; i++)
    245         for (int j = 0; j < 4; j++)
    246             b[i][j] = a[j][i];
    247 }
    248 
    249 // Multiply a homogeneous point by a matrix and return the transformed point
    250 static void v4MulPointByMatrix(const Vector4 p, const TransformationMatrix::Matrix4& m, Vector4 result)
    251 {
    252     result[0] = (p[0] * m[0][0]) + (p[1] * m[1][0]) +
    253                 (p[2] * m[2][0]) + (p[3] * m[3][0]);
    254     result[1] = (p[0] * m[0][1]) + (p[1] * m[1][1]) +
    255                 (p[2] * m[2][1]) + (p[3] * m[3][1]);
    256     result[2] = (p[0] * m[0][2]) + (p[1] * m[1][2]) +
    257                 (p[2] * m[2][2]) + (p[3] * m[3][2]);
    258     result[3] = (p[0] * m[0][3]) + (p[1] * m[1][3]) +
    259                 (p[2] * m[2][3]) + (p[3] * m[3][3]);
    260 }
    261 
    262 static double v3Length(Vector3 a)
    263 {
    264     return sqrt((a[0] * a[0]) + (a[1] * a[1]) + (a[2] * a[2]));
    265 }
    266 
    267 static void v3Scale(Vector3 v, double desiredLength)
    268 {
    269     double len = v3Length(v);
    270     if (len != 0) {
    271         double l = desiredLength / len;
    272         v[0] *= l;
    273         v[1] *= l;
    274         v[2] *= l;
    275     }
    276 }
    277 
    278 static double v3Dot(const Vector3 a, const Vector3 b)
    279 {
    280     return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
    281 }
    282 
    283 // Make a linear combination of two vectors and return the result.
    284 // result = (a * ascl) + (b * bscl)
    285 static void v3Combine(const Vector3 a, const Vector3 b, Vector3 result, double ascl, double bscl)
    286 {
    287     result[0] = (ascl * a[0]) + (bscl * b[0]);
    288     result[1] = (ascl * a[1]) + (bscl * b[1]);
    289     result[2] = (ascl * a[2]) + (bscl * b[2]);
    290 }
    291 
    292 // Return the cross product result = a cross b */
    293 static void v3Cross(const Vector3 a, const Vector3 b, Vector3 result)
    294 {
    295     result[0] = (a[1] * b[2]) - (a[2] * b[1]);
    296     result[1] = (a[2] * b[0]) - (a[0] * b[2]);
    297     result[2] = (a[0] * b[1]) - (a[1] * b[0]);
    298 }
    299 
    300 static bool decompose(const TransformationMatrix::Matrix4& mat, TransformationMatrix::DecomposedType& result)
    301 {
    302     TransformationMatrix::Matrix4 localMatrix;
    303     memcpy(localMatrix, mat, sizeof(TransformationMatrix::Matrix4));
    304 
    305     // Normalize the matrix.
    306     if (localMatrix[3][3] == 0)
    307         return false;
    308 
    309     int i, j;
    310     for (i = 0; i < 4; i++)
    311         for (j = 0; j < 4; j++)
    312             localMatrix[i][j] /= localMatrix[3][3];
    313 
    314     // perspectiveMatrix is used to solve for perspective, but it also provides
    315     // an easy way to test for singularity of the upper 3x3 component.
    316     TransformationMatrix::Matrix4 perspectiveMatrix;
    317     memcpy(perspectiveMatrix, localMatrix, sizeof(TransformationMatrix::Matrix4));
    318     for (i = 0; i < 3; i++)
    319         perspectiveMatrix[i][3] = 0;
    320     perspectiveMatrix[3][3] = 1;
    321 
    322     if (determinant4x4(perspectiveMatrix) == 0)
    323         return false;
    324 
    325     // First, isolate perspective.  This is the messiest.
    326     if (localMatrix[0][3] != 0 || localMatrix[1][3] != 0 || localMatrix[2][3] != 0) {
    327         // rightHandSide is the right hand side of the equation.
    328         Vector4 rightHandSide;
    329         rightHandSide[0] = localMatrix[0][3];
    330         rightHandSide[1] = localMatrix[1][3];
    331         rightHandSide[2] = localMatrix[2][3];
    332         rightHandSide[3] = localMatrix[3][3];
    333 
    334         // Solve the equation by inverting perspectiveMatrix and multiplying
    335         // rightHandSide by the inverse.  (This is the easiest way, not
    336         // necessarily the best.)
    337         TransformationMatrix::Matrix4 inversePerspectiveMatrix, transposedInversePerspectiveMatrix;
    338         inverse(perspectiveMatrix, inversePerspectiveMatrix);
    339         transposeMatrix4(inversePerspectiveMatrix, transposedInversePerspectiveMatrix);
    340 
    341         Vector4 perspectivePoint;
    342         v4MulPointByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspectivePoint);
    343 
    344         result.perspectiveX = perspectivePoint[0];
    345         result.perspectiveY = perspectivePoint[1];
    346         result.perspectiveZ = perspectivePoint[2];
    347         result.perspectiveW = perspectivePoint[3];
    348 
    349         // Clear the perspective partition
    350         localMatrix[0][3] = localMatrix[1][3] = localMatrix[2][3] = 0;
    351         localMatrix[3][3] = 1;
    352     } else {
    353         // No perspective.
    354         result.perspectiveX = result.perspectiveY = result.perspectiveZ = 0;
    355         result.perspectiveW = 1;
    356     }
    357 
    358     // Next take care of translation (easy).
    359     result.translateX = localMatrix[3][0];
    360     localMatrix[3][0] = 0;
    361     result.translateY = localMatrix[3][1];
    362     localMatrix[3][1] = 0;
    363     result.translateZ = localMatrix[3][2];
    364     localMatrix[3][2] = 0;
    365 
    366     // Vector4 type and functions need to be added to the common set.
    367     Vector3 row[3], pdum3;
    368 
    369     // Now get scale and shear.
    370     for (i = 0; i < 3; i++) {
    371         row[i][0] = localMatrix[i][0];
    372         row[i][1] = localMatrix[i][1];
    373         row[i][2] = localMatrix[i][2];
    374     }
    375 
    376     // Compute X scale factor and normalize first row.
    377     result.scaleX = v3Length(row[0]);
    378     v3Scale(row[0], 1.0);
    379 
    380     // Compute XY shear factor and make 2nd row orthogonal to 1st.
    381     result.skewXY = v3Dot(row[0], row[1]);
    382     v3Combine(row[1], row[0], row[1], 1.0, -result.skewXY);
    383 
    384     // Now, compute Y scale and normalize 2nd row.
    385     result.scaleY = v3Length(row[1]);
    386     v3Scale(row[1], 1.0);
    387     result.skewXY /= result.scaleY;
    388 
    389     // Compute XZ and YZ shears, orthogonalize 3rd row.
    390     result.skewXZ = v3Dot(row[0], row[2]);
    391     v3Combine(row[2], row[0], row[2], 1.0, -result.skewXZ);
    392     result.skewYZ = v3Dot(row[1], row[2]);
    393     v3Combine(row[2], row[1], row[2], 1.0, -result.skewYZ);
    394 
    395     // Next, get Z scale and normalize 3rd row.
    396     result.scaleZ = v3Length(row[2]);
    397     v3Scale(row[2], 1.0);
    398     result.skewXZ /= result.scaleZ;
    399     result.skewYZ /= result.scaleZ;
    400 
    401     // At this point, the matrix (in rows[]) is orthonormal.
    402     // Check for a coordinate system flip.  If the determinant
    403     // is -1, then negate the matrix and the scaling factors.
    404     v3Cross(row[1], row[2], pdum3);
    405     if (v3Dot(row[0], pdum3) < 0) {
    406 
    407         result.scaleX *= -1;
    408         result.scaleY *= -1;
    409         result.scaleZ *= -1;
    410 
    411         for (i = 0; i < 3; i++) {
    412             row[i][0] *= -1;
    413             row[i][1] *= -1;
    414             row[i][2] *= -1;
    415         }
    416     }
    417 
    418     // Now, get the rotations out, as described in the gem.
    419 
    420     // FIXME - Add the ability to return either quaternions (which are
    421     // easier to recompose with) or Euler angles (rx, ry, rz), which
    422     // are easier for authors to deal with. The latter will only be useful
    423     // when we fix https://bugs.webkit.org/show_bug.cgi?id=23799, so I
    424     // will leave the Euler angle code here for now.
    425 
    426     // ret.rotateY = asin(-row[0][2]);
    427     // if (cos(ret.rotateY) != 0) {
    428     //     ret.rotateX = atan2(row[1][2], row[2][2]);
    429     //     ret.rotateZ = atan2(row[0][1], row[0][0]);
    430     // } else {
    431     //     ret.rotateX = atan2(-row[2][0], row[1][1]);
    432     //     ret.rotateZ = 0;
    433     // }
    434 
    435     double s, t, x, y, z, w;
    436 
    437     t = row[0][0] + row[1][1] + row[2][2] + 1.0;
    438 
    439     if (t > 1e-4) {
    440         s = 0.5 / sqrt(t);
    441         w = 0.25 / s;
    442         x = (row[2][1] - row[1][2]) * s;
    443         y = (row[0][2] - row[2][0]) * s;
    444         z = (row[1][0] - row[0][1]) * s;
    445     } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) {
    446         s = sqrt (1.0 + row[0][0] - row[1][1] - row[2][2]) * 2.0; // S=4*qx
    447         x = 0.25 * s;
    448         y = (row[0][1] + row[1][0]) / s;
    449         z = (row[0][2] + row[2][0]) / s;
    450         w = (row[2][1] - row[1][2]) / s;
    451     } else if (row[1][1] > row[2][2]) {
    452         s = sqrt (1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; // S=4*qy
    453         x = (row[0][1] + row[1][0]) / s;
    454         y = 0.25 * s;
    455         z = (row[1][2] + row[2][1]) / s;
    456         w = (row[0][2] - row[2][0]) / s;
    457     } else {
    458         s = sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; // S=4*qz
    459         x = (row[0][2] + row[2][0]) / s;
    460         y = (row[1][2] + row[2][1]) / s;
    461         z = 0.25 * s;
    462         w = (row[1][0] - row[0][1]) / s;
    463     }
    464 
    465     result.quaternionX = x;
    466     result.quaternionY = y;
    467     result.quaternionZ = z;
    468     result.quaternionW = w;
    469 
    470     return true;
    471 }
    472 
    473 // Perform a spherical linear interpolation between the two
    474 // passed quaternions with 0 <= t <= 1
    475 static void slerp(double qa[4], const double qb[4], double t)
    476 {
    477     double ax, ay, az, aw;
    478     double bx, by, bz, bw;
    479     double cx, cy, cz, cw;
    480     double angle;
    481     double th, invth, scale, invscale;
    482 
    483     ax = qa[0]; ay = qa[1]; az = qa[2]; aw = qa[3];
    484     bx = qb[0]; by = qb[1]; bz = qb[2]; bw = qb[3];
    485 
    486     angle = ax * bx + ay * by + az * bz + aw * bw;
    487 
    488     if (angle < 0.0) {
    489         ax = -ax; ay = -ay;
    490         az = -az; aw = -aw;
    491         angle = -angle;
    492     }
    493 
    494     if (angle + 1.0 > .05) {
    495         if (1.0 - angle >= .05) {
    496             th = acos (angle);
    497             invth = 1.0 / sin (th);
    498             scale = sin (th * (1.0 - t)) * invth;
    499             invscale = sin (th * t) * invth;
    500         } else {
    501             scale = 1.0 - t;
    502             invscale = t;
    503         }
    504     } else {
    505         bx = -ay;
    506         by = ax;
    507         bz = -aw;
    508         bw = az;
    509         scale = sin(piDouble * (.5 - t));
    510         invscale = sin (piDouble * t);
    511     }
    512 
    513     cx = ax * scale + bx * invscale;
    514     cy = ay * scale + by * invscale;
    515     cz = az * scale + bz * invscale;
    516     cw = aw * scale + bw * invscale;
    517 
    518     qa[0] = cx; qa[1] = cy; qa[2] = cz; qa[3] = cw;
    519 }
    520 
    521 // End of Supporting Math Functions
    522 
    523 TransformationMatrix::TransformationMatrix(const AffineTransform& t)
    524 {
    525     setMatrix(t.a(), t.b(), t.c(), t.d(), t.e(), t.f());
    526 }
    527 
    528 TransformationMatrix& TransformationMatrix::scale(double s)
    529 {
    530     return scaleNonUniform(s, s);
    531 }
    532 
    533 TransformationMatrix& TransformationMatrix::rotateFromVector(double x, double y)
    534 {
    535     return rotate(rad2deg(atan2(y, x)));
    536 }
    537 
    538 TransformationMatrix& TransformationMatrix::flipX()
    539 {
    540     return scaleNonUniform(-1.0, 1.0);
    541 }
    542 
    543 TransformationMatrix& TransformationMatrix::flipY()
    544 {
    545     return scaleNonUniform(1.0, -1.0);
    546 }
    547 
    548 FloatPoint TransformationMatrix::projectPoint(const FloatPoint& p, bool* clamped) const
    549 {
    550     // This is basically raytracing. We have a point in the destination
    551     // plane with z=0, and we cast a ray parallel to the z-axis from that
    552     // point to find the z-position at which it intersects the z=0 plane
    553     // with the transform applied. Once we have that point we apply the
    554     // inverse transform to find the corresponding point in the source
    555     // space.
    556     //
    557     // Given a plane with normal Pn, and a ray starting at point R0 and
    558     // with direction defined by the vector Rd, we can find the
    559     // intersection point as a distance d from R0 in units of Rd by:
    560     //
    561     // d = -dot (Pn', R0) / dot (Pn', Rd)
    562     if (clamped)
    563         *clamped = false;
    564 
    565     if (m33() == 0) {
    566         // In this case, the projection plane is parallel to the ray we are trying to
    567         // trace, and there is no well-defined value for the projection.
    568         return FloatPoint();
    569     }
    570 
    571     double x = p.x();
    572     double y = p.y();
    573     double z = -(m13() * x + m23() * y + m43()) / m33();
    574 
    575     // FIXME: use multVecMatrix()
    576     double outX = x * m11() + y * m21() + z * m31() + m41();
    577     double outY = x * m12() + y * m22() + z * m32() + m42();
    578 
    579     double w = x * m14() + y * m24() + z * m34() + m44();
    580     if (w <= 0) {
    581         // Using int max causes overflow when other code uses the projected point. To
    582         // represent infinity yet reduce the risk of overflow, we use a large but
    583         // not-too-large number here when clamping.
    584         const int largeNumber = 100000000 / kFixedPointDenominator;
    585         outX = copysign(largeNumber, outX);
    586         outY = copysign(largeNumber, outY);
    587         if (clamped)
    588             *clamped = true;
    589     } else if (w != 1) {
    590         outX /= w;
    591         outY /= w;
    592     }
    593 
    594     return FloatPoint(static_cast<float>(outX), static_cast<float>(outY));
    595 }
    596 
    597 FloatQuad TransformationMatrix::projectQuad(const FloatQuad& q, bool* clamped) const
    598 {
    599     FloatQuad projectedQuad;
    600 
    601     bool clamped1 = false;
    602     bool clamped2 = false;
    603     bool clamped3 = false;
    604     bool clamped4 = false;
    605 
    606     projectedQuad.setP1(projectPoint(q.p1(), &clamped1));
    607     projectedQuad.setP2(projectPoint(q.p2(), &clamped2));
    608     projectedQuad.setP3(projectPoint(q.p3(), &clamped3));
    609     projectedQuad.setP4(projectPoint(q.p4(), &clamped4));
    610 
    611     if (clamped)
    612         *clamped = clamped1 || clamped2 || clamped3 || clamped4;
    613 
    614     // If all points on the quad had w < 0, then the entire quad would not be visible to the projected surface.
    615     bool everythingWasClipped = clamped1 && clamped2 && clamped3 && clamped4;
    616     if (everythingWasClipped)
    617         return FloatQuad();
    618 
    619     return projectedQuad;
    620 }
    621 
    622 static float clampEdgeValue(float f)
    623 {
    624     ASSERT(!std::isnan(f));
    625     return min<float>(max<float>(f, -LayoutUnit::max() / 2), LayoutUnit::max() / 2);
    626 }
    627 
    628 LayoutRect TransformationMatrix::clampedBoundsOfProjectedQuad(const FloatQuad& q) const
    629 {
    630     FloatRect mappedQuadBounds = projectQuad(q).boundingBox();
    631 
    632     float left = clampEdgeValue(floorf(mappedQuadBounds.x()));
    633     float top = clampEdgeValue(floorf(mappedQuadBounds.y()));
    634 
    635     float right;
    636     if (std::isinf(mappedQuadBounds.x()) && std::isinf(mappedQuadBounds.width()))
    637         right = LayoutUnit::max() / 2;
    638     else
    639         right = clampEdgeValue(ceilf(mappedQuadBounds.maxX()));
    640 
    641     float bottom;
    642     if (std::isinf(mappedQuadBounds.y()) && std::isinf(mappedQuadBounds.height()))
    643         bottom = LayoutUnit::max() / 2;
    644     else
    645         bottom = clampEdgeValue(ceilf(mappedQuadBounds.maxY()));
    646 
    647     return LayoutRect(LayoutUnit::clamp(left), LayoutUnit::clamp(top),  LayoutUnit::clamp(right - left), LayoutUnit::clamp(bottom - top));
    648 }
    649 
    650 FloatPoint TransformationMatrix::mapPoint(const FloatPoint& p) const
    651 {
    652     if (isIdentityOrTranslation())
    653         return FloatPoint(p.x() + static_cast<float>(m_matrix[3][0]), p.y() + static_cast<float>(m_matrix[3][1]));
    654 
    655     return internalMapPoint(p);
    656 }
    657 
    658 FloatPoint3D TransformationMatrix::mapPoint(const FloatPoint3D& p) const
    659 {
    660     if (isIdentityOrTranslation())
    661         return FloatPoint3D(p.x() + static_cast<float>(m_matrix[3][0]),
    662                             p.y() + static_cast<float>(m_matrix[3][1]),
    663                             p.z() + static_cast<float>(m_matrix[3][2]));
    664 
    665     return internalMapPoint(p);
    666 }
    667 
    668 IntRect TransformationMatrix::mapRect(const IntRect &rect) const
    669 {
    670     return enclosingIntRect(mapRect(FloatRect(rect)));
    671 }
    672 
    673 LayoutRect TransformationMatrix::mapRect(const LayoutRect& r) const
    674 {
    675     return enclosingLayoutRect(mapRect(FloatRect(r)));
    676 }
    677 
    678 FloatRect TransformationMatrix::mapRect(const FloatRect& r) const
    679 {
    680     if (isIdentityOrTranslation()) {
    681         FloatRect mappedRect(r);
    682         mappedRect.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
    683         return mappedRect;
    684     }
    685 
    686     FloatQuad result;
    687 
    688     float maxX = r.maxX();
    689     float maxY = r.maxY();
    690     result.setP1(internalMapPoint(FloatPoint(r.x(), r.y())));
    691     result.setP2(internalMapPoint(FloatPoint(maxX, r.y())));
    692     result.setP3(internalMapPoint(FloatPoint(maxX, maxY)));
    693     result.setP4(internalMapPoint(FloatPoint(r.x(), maxY)));
    694 
    695     return result.boundingBox();
    696 }
    697 
    698 FloatQuad TransformationMatrix::mapQuad(const FloatQuad& q) const
    699 {
    700     if (isIdentityOrTranslation()) {
    701         FloatQuad mappedQuad(q);
    702         mappedQuad.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
    703         return mappedQuad;
    704     }
    705 
    706     FloatQuad result;
    707     result.setP1(internalMapPoint(q.p1()));
    708     result.setP2(internalMapPoint(q.p2()));
    709     result.setP3(internalMapPoint(q.p3()));
    710     result.setP4(internalMapPoint(q.p4()));
    711     return result;
    712 }
    713 
    714 TransformationMatrix& TransformationMatrix::scaleNonUniform(double sx, double sy)
    715 {
    716     m_matrix[0][0] *= sx;
    717     m_matrix[0][1] *= sx;
    718     m_matrix[0][2] *= sx;
    719     m_matrix[0][3] *= sx;
    720 
    721     m_matrix[1][0] *= sy;
    722     m_matrix[1][1] *= sy;
    723     m_matrix[1][2] *= sy;
    724     m_matrix[1][3] *= sy;
    725     return *this;
    726 }
    727 
    728 TransformationMatrix& TransformationMatrix::scale3d(double sx, double sy, double sz)
    729 {
    730     scaleNonUniform(sx, sy);
    731 
    732     m_matrix[2][0] *= sz;
    733     m_matrix[2][1] *= sz;
    734     m_matrix[2][2] *= sz;
    735     m_matrix[2][3] *= sz;
    736     return *this;
    737 }
    738 
    739 TransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double z, double angle)
    740 {
    741     // Normalize the axis of rotation
    742     double length = sqrt(x * x + y * y + z * z);
    743     if (length == 0) {
    744         // A direction vector that cannot be normalized, such as [0, 0, 0], will cause the rotation to not be applied.
    745         return *this;
    746     } else if (length != 1) {
    747         x /= length;
    748         y /= length;
    749         z /= length;
    750     }
    751 
    752     // Angles are in degrees. Switch to radians.
    753     angle = deg2rad(angle);
    754 
    755     double sinTheta = sin(angle);
    756     double cosTheta = cos(angle);
    757 
    758     TransformationMatrix mat;
    759 
    760     // Optimize cases where the axis is along a major axis
    761     if (x == 1.0 && y == 0.0 && z == 0.0) {
    762         mat.m_matrix[0][0] = 1.0;
    763         mat.m_matrix[0][1] = 0.0;
    764         mat.m_matrix[0][2] = 0.0;
    765         mat.m_matrix[1][0] = 0.0;
    766         mat.m_matrix[1][1] = cosTheta;
    767         mat.m_matrix[1][2] = sinTheta;
    768         mat.m_matrix[2][0] = 0.0;
    769         mat.m_matrix[2][1] = -sinTheta;
    770         mat.m_matrix[2][2] = cosTheta;
    771         mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0;
    772         mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0;
    773         mat.m_matrix[3][3] = 1.0;
    774     } else if (x == 0.0 && y == 1.0 && z == 0.0) {
    775         mat.m_matrix[0][0] = cosTheta;
    776         mat.m_matrix[0][1] = 0.0;
    777         mat.m_matrix[0][2] = -sinTheta;
    778         mat.m_matrix[1][0] = 0.0;
    779         mat.m_matrix[1][1] = 1.0;
    780         mat.m_matrix[1][2] = 0.0;
    781         mat.m_matrix[2][0] = sinTheta;
    782         mat.m_matrix[2][1] = 0.0;
    783         mat.m_matrix[2][2] = cosTheta;
    784         mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0;
    785         mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0;
    786         mat.m_matrix[3][3] = 1.0;
    787     } else if (x == 0.0 && y == 0.0 && z == 1.0) {
    788         mat.m_matrix[0][0] = cosTheta;
    789         mat.m_matrix[0][1] = sinTheta;
    790         mat.m_matrix[0][2] = 0.0;
    791         mat.m_matrix[1][0] = -sinTheta;
    792         mat.m_matrix[1][1] = cosTheta;
    793         mat.m_matrix[1][2] = 0.0;
    794         mat.m_matrix[2][0] = 0.0;
    795         mat.m_matrix[2][1] = 0.0;
    796         mat.m_matrix[2][2] = 1.0;
    797         mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0;
    798         mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0;
    799         mat.m_matrix[3][3] = 1.0;
    800     } else {
    801         // This case is the rotation about an arbitrary unit vector.
    802         //
    803         // Formula is adapted from Wikipedia article on Rotation matrix,
    804         // http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
    805         //
    806         // An alternate resource with the same matrix: http://www.fastgraph.com/makegames/3drotation/
    807         //
    808         double oneMinusCosTheta = 1 - cosTheta;
    809         mat.m_matrix[0][0] = cosTheta + x * x * oneMinusCosTheta;
    810         mat.m_matrix[0][1] = y * x * oneMinusCosTheta + z * sinTheta;
    811         mat.m_matrix[0][2] = z * x * oneMinusCosTheta - y * sinTheta;
    812         mat.m_matrix[1][0] = x * y * oneMinusCosTheta - z * sinTheta;
    813         mat.m_matrix[1][1] = cosTheta + y * y * oneMinusCosTheta;
    814         mat.m_matrix[1][2] = z * y * oneMinusCosTheta + x * sinTheta;
    815         mat.m_matrix[2][0] = x * z * oneMinusCosTheta + y * sinTheta;
    816         mat.m_matrix[2][1] = y * z * oneMinusCosTheta - x * sinTheta;
    817         mat.m_matrix[2][2] = cosTheta + z * z * oneMinusCosTheta;
    818         mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0;
    819         mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0;
    820         mat.m_matrix[3][3] = 1.0;
    821     }
    822     multiply(mat);
    823     return *this;
    824 }
    825 
    826 TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, double rz)
    827 {
    828     // Angles are in degrees. Switch to radians.
    829     rx = deg2rad(rx);
    830     ry = deg2rad(ry);
    831     rz = deg2rad(rz);
    832 
    833     TransformationMatrix mat;
    834 
    835     double sinTheta = sin(rz);
    836     double cosTheta = cos(rz);
    837 
    838     mat.m_matrix[0][0] = cosTheta;
    839     mat.m_matrix[0][1] = sinTheta;
    840     mat.m_matrix[0][2] = 0.0;
    841     mat.m_matrix[1][0] = -sinTheta;
    842     mat.m_matrix[1][1] = cosTheta;
    843     mat.m_matrix[1][2] = 0.0;
    844     mat.m_matrix[2][0] = 0.0;
    845     mat.m_matrix[2][1] = 0.0;
    846     mat.m_matrix[2][2] = 1.0;
    847     mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0;
    848     mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0;
    849     mat.m_matrix[3][3] = 1.0;
    850 
    851     TransformationMatrix rmat(mat);
    852 
    853     sinTheta = sin(ry);
    854     cosTheta = cos(ry);
    855 
    856     mat.m_matrix[0][0] = cosTheta;
    857     mat.m_matrix[0][1] = 0.0;
    858     mat.m_matrix[0][2] = -sinTheta;
    859     mat.m_matrix[1][0] = 0.0;
    860     mat.m_matrix[1][1] = 1.0;
    861     mat.m_matrix[1][2] = 0.0;
    862     mat.m_matrix[2][0] = sinTheta;
    863     mat.m_matrix[2][1] = 0.0;
    864     mat.m_matrix[2][2] = cosTheta;
    865     mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0;
    866     mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0;
    867     mat.m_matrix[3][3] = 1.0;
    868 
    869     rmat.multiply(mat);
    870 
    871     sinTheta = sin(rx);
    872     cosTheta = cos(rx);
    873 
    874     mat.m_matrix[0][0] = 1.0;
    875     mat.m_matrix[0][1] = 0.0;
    876     mat.m_matrix[0][2] = 0.0;
    877     mat.m_matrix[1][0] = 0.0;
    878     mat.m_matrix[1][1] = cosTheta;
    879     mat.m_matrix[1][2] = sinTheta;
    880     mat.m_matrix[2][0] = 0.0;
    881     mat.m_matrix[2][1] = -sinTheta;
    882     mat.m_matrix[2][2] = cosTheta;
    883     mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0;
    884     mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0;
    885     mat.m_matrix[3][3] = 1.0;
    886 
    887     rmat.multiply(mat);
    888 
    889     multiply(rmat);
    890     return *this;
    891 }
    892 
    893 TransformationMatrix& TransformationMatrix::translate(double tx, double ty)
    894 {
    895     m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0];
    896     m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1];
    897     m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2];
    898     m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3];
    899     return *this;
    900 }
    901 
    902 TransformationMatrix& TransformationMatrix::translate3d(double tx, double ty, double tz)
    903 {
    904     m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0] + tz * m_matrix[2][0];
    905     m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1] + tz * m_matrix[2][1];
    906     m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2] + tz * m_matrix[2][2];
    907     m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3] + tz * m_matrix[2][3];
    908     return *this;
    909 }
    910 
    911 TransformationMatrix& TransformationMatrix::translateRight(double tx, double ty)
    912 {
    913     if (tx != 0) {
    914         m_matrix[0][0] +=  m_matrix[0][3] * tx;
    915         m_matrix[1][0] +=  m_matrix[1][3] * tx;
    916         m_matrix[2][0] +=  m_matrix[2][3] * tx;
    917         m_matrix[3][0] +=  m_matrix[3][3] * tx;
    918     }
    919 
    920     if (ty != 0) {
    921         m_matrix[0][1] +=  m_matrix[0][3] * ty;
    922         m_matrix[1][1] +=  m_matrix[1][3] * ty;
    923         m_matrix[2][1] +=  m_matrix[2][3] * ty;
    924         m_matrix[3][1] +=  m_matrix[3][3] * ty;
    925     }
    926 
    927     return *this;
    928 }
    929 
    930 TransformationMatrix& TransformationMatrix::translateRight3d(double tx, double ty, double tz)
    931 {
    932     translateRight(tx, ty);
    933     if (tz != 0) {
    934         m_matrix[0][2] +=  m_matrix[0][3] * tz;
    935         m_matrix[1][2] +=  m_matrix[1][3] * tz;
    936         m_matrix[2][2] +=  m_matrix[2][3] * tz;
    937         m_matrix[3][2] +=  m_matrix[3][3] * tz;
    938     }
    939 
    940     return *this;
    941 }
    942 
    943 TransformationMatrix& TransformationMatrix::skew(double sx, double sy)
    944 {
    945     // angles are in degrees. Switch to radians
    946     sx = deg2rad(sx);
    947     sy = deg2rad(sy);
    948 
    949     TransformationMatrix mat;
    950     mat.m_matrix[0][1] = tan(sy); // note that the y shear goes in the first row
    951     mat.m_matrix[1][0] = tan(sx); // and the x shear in the second row
    952 
    953     multiply(mat);
    954     return *this;
    955 }
    956 
    957 TransformationMatrix& TransformationMatrix::applyPerspective(double p)
    958 {
    959     TransformationMatrix mat;
    960     if (p != 0)
    961         mat.m_matrix[2][3] = -1/p;
    962 
    963     multiply(mat);
    964     return *this;
    965 }
    966 
    967 TransformationMatrix TransformationMatrix::rectToRect(const FloatRect& from, const FloatRect& to)
    968 {
    969     ASSERT(!from.isEmpty());
    970     return TransformationMatrix(to.width() / from.width(),
    971                                 0, 0,
    972                                 to.height() / from.height(),
    973                                 to.x() - from.x(),
    974                                 to.y() - from.y());
    975 }
    976 
    977 // this = mat * this.
    978 TransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& mat)
    979 {
    980 #if CPU(APPLE_ARMV7S)
    981     double* leftMatrix = &(m_matrix[0][0]);
    982     const double* rightMatrix = &(mat.m_matrix[0][0]);
    983     asm volatile (// First row of leftMatrix.
    984         "mov        r3, %[leftMatrix]\n\t"
    985         "vld1.64    { d16-d19 }, [%[leftMatrix], :128]!\n\t"
    986         "vld1.64    { d0-d3}, [%[rightMatrix], :128]!\n\t"
    987         "vmul.f64   d4, d0, d16\n\t"
    988         "vld1.64    { d20-d23 }, [%[leftMatrix], :128]!\n\t"
    989         "vmla.f64   d4, d1, d20\n\t"
    990         "vld1.64    { d24-d27 }, [%[leftMatrix], :128]!\n\t"
    991         "vmla.f64   d4, d2, d24\n\t"
    992         "vld1.64    { d28-d31 }, [%[leftMatrix], :128]!\n\t"
    993         "vmla.f64   d4, d3, d28\n\t"
    994 
    995         "vmul.f64   d5, d0, d17\n\t"
    996         "vmla.f64   d5, d1, d21\n\t"
    997         "vmla.f64   d5, d2, d25\n\t"
    998         "vmla.f64   d5, d3, d29\n\t"
    999 
   1000         "vmul.f64   d6, d0, d18\n\t"
   1001         "vmla.f64   d6, d1, d22\n\t"
   1002         "vmla.f64   d6, d2, d26\n\t"
   1003         "vmla.f64   d6, d3, d30\n\t"
   1004 
   1005         "vmul.f64   d7, d0, d19\n\t"
   1006         "vmla.f64   d7, d1, d23\n\t"
   1007         "vmla.f64   d7, d2, d27\n\t"
   1008         "vmla.f64   d7, d3, d31\n\t"
   1009         "vld1.64    { d0-d3}, [%[rightMatrix], :128]!\n\t"
   1010         "vst1.64    { d4-d7 }, [r3, :128]!\n\t"
   1011 
   1012         // Second row of leftMatrix.
   1013         "vmul.f64   d4, d0, d16\n\t"
   1014         "vmla.f64   d4, d1, d20\n\t"
   1015         "vmla.f64   d4, d2, d24\n\t"
   1016         "vmla.f64   d4, d3, d28\n\t"
   1017 
   1018         "vmul.f64   d5, d0, d17\n\t"
   1019         "vmla.f64   d5, d1, d21\n\t"
   1020         "vmla.f64   d5, d2, d25\n\t"
   1021         "vmla.f64   d5, d3, d29\n\t"
   1022 
   1023         "vmul.f64   d6, d0, d18\n\t"
   1024         "vmla.f64   d6, d1, d22\n\t"
   1025         "vmla.f64   d6, d2, d26\n\t"
   1026         "vmla.f64   d6, d3, d30\n\t"
   1027 
   1028         "vmul.f64   d7, d0, d19\n\t"
   1029         "vmla.f64   d7, d1, d23\n\t"
   1030         "vmla.f64   d7, d2, d27\n\t"
   1031         "vmla.f64   d7, d3, d31\n\t"
   1032         "vld1.64    { d0-d3}, [%[rightMatrix], :128]!\n\t"
   1033         "vst1.64    { d4-d7 }, [r3, :128]!\n\t"
   1034 
   1035         // Third row of leftMatrix.
   1036         "vmul.f64   d4, d0, d16\n\t"
   1037         "vmla.f64   d4, d1, d20\n\t"
   1038         "vmla.f64   d4, d2, d24\n\t"
   1039         "vmla.f64   d4, d3, d28\n\t"
   1040 
   1041         "vmul.f64   d5, d0, d17\n\t"
   1042         "vmla.f64   d5, d1, d21\n\t"
   1043         "vmla.f64   d5, d2, d25\n\t"
   1044         "vmla.f64   d5, d3, d29\n\t"
   1045 
   1046         "vmul.f64   d6, d0, d18\n\t"
   1047         "vmla.f64   d6, d1, d22\n\t"
   1048         "vmla.f64   d6, d2, d26\n\t"
   1049         "vmla.f64   d6, d3, d30\n\t"
   1050 
   1051         "vmul.f64   d7, d0, d19\n\t"
   1052         "vmla.f64   d7, d1, d23\n\t"
   1053         "vmla.f64   d7, d2, d27\n\t"
   1054         "vmla.f64   d7, d3, d31\n\t"
   1055         "vld1.64    { d0-d3}, [%[rightMatrix], :128]\n\t"
   1056         "vst1.64    { d4-d7 }, [r3, :128]!\n\t"
   1057 
   1058         // Fourth and last row of leftMatrix.
   1059         "vmul.f64   d4, d0, d16\n\t"
   1060         "vmla.f64   d4, d1, d20\n\t"
   1061         "vmla.f64   d4, d2, d24\n\t"
   1062         "vmla.f64   d4, d3, d28\n\t"
   1063 
   1064         "vmul.f64   d5, d0, d17\n\t"
   1065         "vmla.f64   d5, d1, d21\n\t"
   1066         "vmla.f64   d5, d2, d25\n\t"
   1067         "vmla.f64   d5, d3, d29\n\t"
   1068 
   1069         "vmul.f64   d6, d0, d18\n\t"
   1070         "vmla.f64   d6, d1, d22\n\t"
   1071         "vmla.f64   d6, d2, d26\n\t"
   1072         "vmla.f64   d6, d3, d30\n\t"
   1073 
   1074         "vmul.f64   d7, d0, d19\n\t"
   1075         "vmla.f64   d7, d1, d23\n\t"
   1076         "vmla.f64   d7, d2, d27\n\t"
   1077         "vmla.f64   d7, d3, d31\n\t"
   1078         "vst1.64    { d4-d7 }, [r3, :128]\n\t"
   1079         : [leftMatrix]"+r"(leftMatrix), [rightMatrix]"+r"(rightMatrix)
   1080         :
   1081         : "memory", "r3", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31");
   1082 #elif defined(TRANSFORMATION_MATRIX_USE_X86_64_SSE2)
   1083     // x86_64 has 16 XMM registers which is enough to do the multiplication fully in registers.
   1084     __m128d matrixBlockA = _mm_load_pd(&(m_matrix[0][0]));
   1085     __m128d matrixBlockC = _mm_load_pd(&(m_matrix[1][0]));
   1086     __m128d matrixBlockE = _mm_load_pd(&(m_matrix[2][0]));
   1087     __m128d matrixBlockG = _mm_load_pd(&(m_matrix[3][0]));
   1088 
   1089     // First row.
   1090     __m128d otherMatrixFirstParam = _mm_set1_pd(mat.m_matrix[0][0]);
   1091     __m128d otherMatrixSecondParam = _mm_set1_pd(mat.m_matrix[0][1]);
   1092     __m128d otherMatrixThirdParam = _mm_set1_pd(mat.m_matrix[0][2]);
   1093     __m128d otherMatrixFourthParam = _mm_set1_pd(mat.m_matrix[0][3]);
   1094 
   1095     // output00 and output01.
   1096     __m128d accumulator = _mm_mul_pd(matrixBlockA, otherMatrixFirstParam);
   1097     __m128d temp1 = _mm_mul_pd(matrixBlockC, otherMatrixSecondParam);
   1098     __m128d temp2 = _mm_mul_pd(matrixBlockE, otherMatrixThirdParam);
   1099     __m128d temp3 = _mm_mul_pd(matrixBlockG, otherMatrixFourthParam);
   1100 
   1101     __m128d matrixBlockB = _mm_load_pd(&(m_matrix[0][2]));
   1102     __m128d matrixBlockD = _mm_load_pd(&(m_matrix[1][2]));
   1103     __m128d matrixBlockF = _mm_load_pd(&(m_matrix[2][2]));
   1104     __m128d matrixBlockH = _mm_load_pd(&(m_matrix[3][2]));
   1105 
   1106     accumulator = _mm_add_pd(accumulator, temp1);
   1107     accumulator = _mm_add_pd(accumulator, temp2);
   1108     accumulator = _mm_add_pd(accumulator, temp3);
   1109     _mm_store_pd(&m_matrix[0][0], accumulator);
   1110 
   1111     // output02 and output03.
   1112     accumulator = _mm_mul_pd(matrixBlockB, otherMatrixFirstParam);
   1113     temp1 = _mm_mul_pd(matrixBlockD, otherMatrixSecondParam);
   1114     temp2 = _mm_mul_pd(matrixBlockF, otherMatrixThirdParam);
   1115     temp3 = _mm_mul_pd(matrixBlockH, otherMatrixFourthParam);
   1116 
   1117     accumulator = _mm_add_pd(accumulator, temp1);
   1118     accumulator = _mm_add_pd(accumulator, temp2);
   1119     accumulator = _mm_add_pd(accumulator, temp3);
   1120     _mm_store_pd(&m_matrix[0][2], accumulator);
   1121 
   1122     // Second row.
   1123     otherMatrixFirstParam = _mm_set1_pd(mat.m_matrix[1][0]);
   1124     otherMatrixSecondParam = _mm_set1_pd(mat.m_matrix[1][1]);
   1125     otherMatrixThirdParam = _mm_set1_pd(mat.m_matrix[1][2]);
   1126     otherMatrixFourthParam = _mm_set1_pd(mat.m_matrix[1][3]);
   1127 
   1128     // output10 and output11.
   1129     accumulator = _mm_mul_pd(matrixBlockA, otherMatrixFirstParam);
   1130     temp1 = _mm_mul_pd(matrixBlockC, otherMatrixSecondParam);
   1131     temp2 = _mm_mul_pd(matrixBlockE, otherMatrixThirdParam);
   1132     temp3 = _mm_mul_pd(matrixBlockG, otherMatrixFourthParam);
   1133 
   1134     accumulator = _mm_add_pd(accumulator, temp1);
   1135     accumulator = _mm_add_pd(accumulator, temp2);
   1136     accumulator = _mm_add_pd(accumulator, temp3);
   1137     _mm_store_pd(&m_matrix[1][0], accumulator);
   1138 
   1139     // output12 and output13.
   1140     accumulator = _mm_mul_pd(matrixBlockB, otherMatrixFirstParam);
   1141     temp1 = _mm_mul_pd(matrixBlockD, otherMatrixSecondParam);
   1142     temp2 = _mm_mul_pd(matrixBlockF, otherMatrixThirdParam);
   1143     temp3 = _mm_mul_pd(matrixBlockH, otherMatrixFourthParam);
   1144 
   1145     accumulator = _mm_add_pd(accumulator, temp1);
   1146     accumulator = _mm_add_pd(accumulator, temp2);
   1147     accumulator = _mm_add_pd(accumulator, temp3);
   1148     _mm_store_pd(&m_matrix[1][2], accumulator);
   1149 
   1150     // Third row.
   1151     otherMatrixFirstParam = _mm_set1_pd(mat.m_matrix[2][0]);
   1152     otherMatrixSecondParam = _mm_set1_pd(mat.m_matrix[2][1]);
   1153     otherMatrixThirdParam = _mm_set1_pd(mat.m_matrix[2][2]);
   1154     otherMatrixFourthParam = _mm_set1_pd(mat.m_matrix[2][3]);
   1155 
   1156     // output20 and output21.
   1157     accumulator = _mm_mul_pd(matrixBlockA, otherMatrixFirstParam);
   1158     temp1 = _mm_mul_pd(matrixBlockC, otherMatrixSecondParam);
   1159     temp2 = _mm_mul_pd(matrixBlockE, otherMatrixThirdParam);
   1160     temp3 = _mm_mul_pd(matrixBlockG, otherMatrixFourthParam);
   1161 
   1162     accumulator = _mm_add_pd(accumulator, temp1);
   1163     accumulator = _mm_add_pd(accumulator, temp2);
   1164     accumulator = _mm_add_pd(accumulator, temp3);
   1165     _mm_store_pd(&m_matrix[2][0], accumulator);
   1166 
   1167     // output22 and output23.
   1168     accumulator = _mm_mul_pd(matrixBlockB, otherMatrixFirstParam);
   1169     temp1 = _mm_mul_pd(matrixBlockD, otherMatrixSecondParam);
   1170     temp2 = _mm_mul_pd(matrixBlockF, otherMatrixThirdParam);
   1171     temp3 = _mm_mul_pd(matrixBlockH, otherMatrixFourthParam);
   1172 
   1173     accumulator = _mm_add_pd(accumulator, temp1);
   1174     accumulator = _mm_add_pd(accumulator, temp2);
   1175     accumulator = _mm_add_pd(accumulator, temp3);
   1176     _mm_store_pd(&m_matrix[2][2], accumulator);
   1177 
   1178     // Fourth row.
   1179     otherMatrixFirstParam = _mm_set1_pd(mat.m_matrix[3][0]);
   1180     otherMatrixSecondParam = _mm_set1_pd(mat.m_matrix[3][1]);
   1181     otherMatrixThirdParam = _mm_set1_pd(mat.m_matrix[3][2]);
   1182     otherMatrixFourthParam = _mm_set1_pd(mat.m_matrix[3][3]);
   1183 
   1184     // output30 and output31.
   1185     accumulator = _mm_mul_pd(matrixBlockA, otherMatrixFirstParam);
   1186     temp1 = _mm_mul_pd(matrixBlockC, otherMatrixSecondParam);
   1187     temp2 = _mm_mul_pd(matrixBlockE, otherMatrixThirdParam);
   1188     temp3 = _mm_mul_pd(matrixBlockG, otherMatrixFourthParam);
   1189 
   1190     accumulator = _mm_add_pd(accumulator, temp1);
   1191     accumulator = _mm_add_pd(accumulator, temp2);
   1192     accumulator = _mm_add_pd(accumulator, temp3);
   1193     _mm_store_pd(&m_matrix[3][0], accumulator);
   1194 
   1195     // output32 and output33.
   1196     accumulator = _mm_mul_pd(matrixBlockB, otherMatrixFirstParam);
   1197     temp1 = _mm_mul_pd(matrixBlockD, otherMatrixSecondParam);
   1198     temp2 = _mm_mul_pd(matrixBlockF, otherMatrixThirdParam);
   1199     temp3 = _mm_mul_pd(matrixBlockH, otherMatrixFourthParam);
   1200 
   1201     accumulator = _mm_add_pd(accumulator, temp1);
   1202     accumulator = _mm_add_pd(accumulator, temp2);
   1203     accumulator = _mm_add_pd(accumulator, temp3);
   1204     _mm_store_pd(&m_matrix[3][2], accumulator);
   1205 #else
   1206     Matrix4 tmp;
   1207 
   1208     tmp[0][0] = (mat.m_matrix[0][0] * m_matrix[0][0] + mat.m_matrix[0][1] * m_matrix[1][0]
   1209                + mat.m_matrix[0][2] * m_matrix[2][0] + mat.m_matrix[0][3] * m_matrix[3][0]);
   1210     tmp[0][1] = (mat.m_matrix[0][0] * m_matrix[0][1] + mat.m_matrix[0][1] * m_matrix[1][1]
   1211                + mat.m_matrix[0][2] * m_matrix[2][1] + mat.m_matrix[0][3] * m_matrix[3][1]);
   1212     tmp[0][2] = (mat.m_matrix[0][0] * m_matrix[0][2] + mat.m_matrix[0][1] * m_matrix[1][2]
   1213                + mat.m_matrix[0][2] * m_matrix[2][2] + mat.m_matrix[0][3] * m_matrix[3][2]);
   1214     tmp[0][3] = (mat.m_matrix[0][0] * m_matrix[0][3] + mat.m_matrix[0][1] * m_matrix[1][3]
   1215                + mat.m_matrix[0][2] * m_matrix[2][3] + mat.m_matrix[0][3] * m_matrix[3][3]);
   1216 
   1217     tmp[1][0] = (mat.m_matrix[1][0] * m_matrix[0][0] + mat.m_matrix[1][1] * m_matrix[1][0]
   1218                + mat.m_matrix[1][2] * m_matrix[2][0] + mat.m_matrix[1][3] * m_matrix[3][0]);
   1219     tmp[1][1] = (mat.m_matrix[1][0] * m_matrix[0][1] + mat.m_matrix[1][1] * m_matrix[1][1]
   1220                + mat.m_matrix[1][2] * m_matrix[2][1] + mat.m_matrix[1][3] * m_matrix[3][1]);
   1221     tmp[1][2] = (mat.m_matrix[1][0] * m_matrix[0][2] + mat.m_matrix[1][1] * m_matrix[1][2]
   1222                + mat.m_matrix[1][2] * m_matrix[2][2] + mat.m_matrix[1][3] * m_matrix[3][2]);
   1223     tmp[1][3] = (mat.m_matrix[1][0] * m_matrix[0][3] + mat.m_matrix[1][1] * m_matrix[1][3]
   1224                + mat.m_matrix[1][2] * m_matrix[2][3] + mat.m_matrix[1][3] * m_matrix[3][3]);
   1225 
   1226     tmp[2][0] = (mat.m_matrix[2][0] * m_matrix[0][0] + mat.m_matrix[2][1] * m_matrix[1][0]
   1227                + mat.m_matrix[2][2] * m_matrix[2][0] + mat.m_matrix[2][3] * m_matrix[3][0]);
   1228     tmp[2][1] = (mat.m_matrix[2][0] * m_matrix[0][1] + mat.m_matrix[2][1] * m_matrix[1][1]
   1229                + mat.m_matrix[2][2] * m_matrix[2][1] + mat.m_matrix[2][3] * m_matrix[3][1]);
   1230     tmp[2][2] = (mat.m_matrix[2][0] * m_matrix[0][2] + mat.m_matrix[2][1] * m_matrix[1][2]
   1231                + mat.m_matrix[2][2] * m_matrix[2][2] + mat.m_matrix[2][3] * m_matrix[3][2]);
   1232     tmp[2][3] = (mat.m_matrix[2][0] * m_matrix[0][3] + mat.m_matrix[2][1] * m_matrix[1][3]
   1233                + mat.m_matrix[2][2] * m_matrix[2][3] + mat.m_matrix[2][3] * m_matrix[3][3]);
   1234 
   1235     tmp[3][0] = (mat.m_matrix[3][0] * m_matrix[0][0] + mat.m_matrix[3][1] * m_matrix[1][0]
   1236                + mat.m_matrix[3][2] * m_matrix[2][0] + mat.m_matrix[3][3] * m_matrix[3][0]);
   1237     tmp[3][1] = (mat.m_matrix[3][0] * m_matrix[0][1] + mat.m_matrix[3][1] * m_matrix[1][1]
   1238                + mat.m_matrix[3][2] * m_matrix[2][1] + mat.m_matrix[3][3] * m_matrix[3][1]);
   1239     tmp[3][2] = (mat.m_matrix[3][0] * m_matrix[0][2] + mat.m_matrix[3][1] * m_matrix[1][2]
   1240                + mat.m_matrix[3][2] * m_matrix[2][2] + mat.m_matrix[3][3] * m_matrix[3][2]);
   1241     tmp[3][3] = (mat.m_matrix[3][0] * m_matrix[0][3] + mat.m_matrix[3][1] * m_matrix[1][3]
   1242                + mat.m_matrix[3][2] * m_matrix[2][3] + mat.m_matrix[3][3] * m_matrix[3][3]);
   1243 
   1244     setMatrix(tmp);
   1245 #endif
   1246     return *this;
   1247 }
   1248 
   1249 void TransformationMatrix::multVecMatrix(double x, double y, double& resultX, double& resultY) const
   1250 {
   1251     resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0];
   1252     resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1];
   1253     double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3];
   1254     if (w != 1 && w != 0) {
   1255         resultX /= w;
   1256         resultY /= w;
   1257     }
   1258 }
   1259 
   1260 void TransformationMatrix::multVecMatrix(double x, double y, double z, double& resultX, double& resultY, double& resultZ) const
   1261 {
   1262     resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0] + z * m_matrix[2][0];
   1263     resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1] + z * m_matrix[2][1];
   1264     resultZ = m_matrix[3][2] + x * m_matrix[0][2] + y * m_matrix[1][2] + z * m_matrix[2][2];
   1265     double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3] + z * m_matrix[2][3];
   1266     if (w != 1 && w != 0) {
   1267         resultX /= w;
   1268         resultY /= w;
   1269         resultZ /= w;
   1270     }
   1271 }
   1272 
   1273 bool TransformationMatrix::isInvertible() const
   1274 {
   1275     if (isIdentityOrTranslation())
   1276         return true;
   1277 
   1278     double det = WebCore::determinant4x4(m_matrix);
   1279 
   1280     if (fabs(det) < SMALL_NUMBER)
   1281         return false;
   1282 
   1283     return true;
   1284 }
   1285 
   1286 TransformationMatrix TransformationMatrix::inverse() const
   1287 {
   1288     if (isIdentityOrTranslation()) {
   1289         // identity matrix
   1290         if (m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0)
   1291             return TransformationMatrix();
   1292 
   1293         // translation
   1294         return TransformationMatrix(1, 0, 0, 0,
   1295                                     0, 1, 0, 0,
   1296                                     0, 0, 1, 0,
   1297                                     -m_matrix[3][0], -m_matrix[3][1], -m_matrix[3][2], 1);
   1298     }
   1299 
   1300     TransformationMatrix invMat;
   1301     bool inverted = WebCore::inverse(m_matrix, invMat.m_matrix);
   1302     if (!inverted)
   1303         return TransformationMatrix();
   1304 
   1305     return invMat;
   1306 }
   1307 
   1308 void TransformationMatrix::makeAffine()
   1309 {
   1310     m_matrix[0][2] = 0;
   1311     m_matrix[0][3] = 0;
   1312 
   1313     m_matrix[1][2] = 0;
   1314     m_matrix[1][3] = 0;
   1315 
   1316     m_matrix[2][0] = 0;
   1317     m_matrix[2][1] = 0;
   1318     m_matrix[2][2] = 1;
   1319     m_matrix[2][3] = 0;
   1320 
   1321     m_matrix[3][2] = 0;
   1322     m_matrix[3][3] = 1;
   1323 }
   1324 
   1325 AffineTransform TransformationMatrix::toAffineTransform() const
   1326 {
   1327     return AffineTransform(m_matrix[0][0], m_matrix[0][1], m_matrix[1][0],
   1328                            m_matrix[1][1], m_matrix[3][0], m_matrix[3][1]);
   1329 }
   1330 
   1331 TransformationMatrix::operator SkMatrix() const
   1332 {
   1333     SkMatrix result;
   1334 
   1335     result.setScaleX(WebCoreDoubleToSkScalar(a()));
   1336     result.setSkewX(WebCoreDoubleToSkScalar(c()));
   1337     result.setTranslateX(WebCoreDoubleToSkScalar(e()));
   1338 
   1339     result.setScaleY(WebCoreDoubleToSkScalar(d()));
   1340     result.setSkewY(WebCoreDoubleToSkScalar(b()));
   1341     result.setTranslateY(WebCoreDoubleToSkScalar(f()));
   1342 
   1343     // FIXME: Set perspective properly.
   1344     result.setPerspX(0);
   1345     result.setPerspY(0);
   1346     result.set(SkMatrix::kMPersp2, SK_Scalar1);
   1347 
   1348     return result;
   1349 }
   1350 
   1351 static inline void blendFloat(double& from, double to, double progress)
   1352 {
   1353     if (from != to)
   1354         from = from + (to - from) * progress;
   1355 }
   1356 
   1357 void TransformationMatrix::blend(const TransformationMatrix& from, double progress)
   1358 {
   1359     if (from.isIdentity() && isIdentity())
   1360         return;
   1361 
   1362     // decompose
   1363     DecomposedType fromDecomp;
   1364     DecomposedType toDecomp;
   1365     from.decompose(fromDecomp);
   1366     decompose(toDecomp);
   1367 
   1368     // interpolate
   1369     blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress);
   1370     blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress);
   1371     blendFloat(fromDecomp.scaleZ, toDecomp.scaleZ, progress);
   1372     blendFloat(fromDecomp.skewXY, toDecomp.skewXY, progress);
   1373     blendFloat(fromDecomp.skewXZ, toDecomp.skewXZ, progress);
   1374     blendFloat(fromDecomp.skewYZ, toDecomp.skewYZ, progress);
   1375     blendFloat(fromDecomp.translateX, toDecomp.translateX, progress);
   1376     blendFloat(fromDecomp.translateY, toDecomp.translateY, progress);
   1377     blendFloat(fromDecomp.translateZ, toDecomp.translateZ, progress);
   1378     blendFloat(fromDecomp.perspectiveX, toDecomp.perspectiveX, progress);
   1379     blendFloat(fromDecomp.perspectiveY, toDecomp.perspectiveY, progress);
   1380     blendFloat(fromDecomp.perspectiveZ, toDecomp.perspectiveZ, progress);
   1381     blendFloat(fromDecomp.perspectiveW, toDecomp.perspectiveW, progress);
   1382 
   1383     slerp(&fromDecomp.quaternionX, &toDecomp.quaternionX, progress);
   1384 
   1385     // recompose
   1386     recompose(fromDecomp);
   1387 }
   1388 
   1389 bool TransformationMatrix::decompose(DecomposedType& decomp) const
   1390 {
   1391     if (isIdentity()) {
   1392         memset(&decomp, 0, sizeof(decomp));
   1393         decomp.perspectiveW = 1;
   1394         decomp.scaleX = 1;
   1395         decomp.scaleY = 1;
   1396         decomp.scaleZ = 1;
   1397     }
   1398 
   1399     if (!WebCore::decompose(m_matrix, decomp))
   1400         return false;
   1401     return true;
   1402 }
   1403 
   1404 void TransformationMatrix::recompose(const DecomposedType& decomp)
   1405 {
   1406     makeIdentity();
   1407 
   1408     // first apply perspective
   1409     m_matrix[0][3] = decomp.perspectiveX;
   1410     m_matrix[1][3] = decomp.perspectiveY;
   1411     m_matrix[2][3] = decomp.perspectiveZ;
   1412     m_matrix[3][3] = decomp.perspectiveW;
   1413 
   1414     // now translate
   1415     translate3d(decomp.translateX, decomp.translateY, decomp.translateZ);
   1416 
   1417     // apply rotation
   1418     double xx = decomp.quaternionX * decomp.quaternionX;
   1419     double xy = decomp.quaternionX * decomp.quaternionY;
   1420     double xz = decomp.quaternionX * decomp.quaternionZ;
   1421     double xw = decomp.quaternionX * decomp.quaternionW;
   1422     double yy = decomp.quaternionY * decomp.quaternionY;
   1423     double yz = decomp.quaternionY * decomp.quaternionZ;
   1424     double yw = decomp.quaternionY * decomp.quaternionW;
   1425     double zz = decomp.quaternionZ * decomp.quaternionZ;
   1426     double zw = decomp.quaternionZ * decomp.quaternionW;
   1427 
   1428     // Construct a composite rotation matrix from the quaternion values
   1429     TransformationMatrix rotationMatrix(1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0,
   1430                            2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0,
   1431                            2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0,
   1432                            0, 0, 0, 1);
   1433 
   1434     multiply(rotationMatrix);
   1435 
   1436     // now apply skew
   1437     if (decomp.skewYZ) {
   1438         TransformationMatrix tmp;
   1439         tmp.setM32(decomp.skewYZ);
   1440         multiply(tmp);
   1441     }
   1442 
   1443     if (decomp.skewXZ) {
   1444         TransformationMatrix tmp;
   1445         tmp.setM31(decomp.skewXZ);
   1446         multiply(tmp);
   1447     }
   1448 
   1449     if (decomp.skewXY) {
   1450         TransformationMatrix tmp;
   1451         tmp.setM21(decomp.skewXY);
   1452         multiply(tmp);
   1453     }
   1454 
   1455     // finally, apply scale
   1456     scale3d(decomp.scaleX, decomp.scaleY, decomp.scaleZ);
   1457 }
   1458 
   1459 bool TransformationMatrix::isIntegerTranslation() const
   1460 {
   1461     if (!isIdentityOrTranslation())
   1462         return false;
   1463 
   1464     // Check for translate Z.
   1465     if (m_matrix[3][2])
   1466         return false;
   1467 
   1468     // Check for non-integer translate X/Y.
   1469     if (static_cast<int>(m_matrix[3][0]) != m_matrix[3][0] || static_cast<int>(m_matrix[3][1]) != m_matrix[3][1])
   1470         return false;
   1471 
   1472     return true;
   1473 }
   1474 
   1475 TransformationMatrix TransformationMatrix::to2dTransform() const
   1476 {
   1477     return TransformationMatrix(m_matrix[0][0], m_matrix[0][1], 0, m_matrix[0][3],
   1478                                 m_matrix[1][0], m_matrix[1][1], 0, m_matrix[1][3],
   1479                                 0, 0, 1, 0,
   1480                                 m_matrix[3][0], m_matrix[3][1], 0, m_matrix[3][3]);
   1481 }
   1482 
   1483 void TransformationMatrix::toColumnMajorFloatArray(FloatMatrix4& result) const
   1484 {
   1485     result[0] = m11();
   1486     result[1] = m12();
   1487     result[2] = m13();
   1488     result[3] = m14();
   1489     result[4] = m21();
   1490     result[5] = m22();
   1491     result[6] = m23();
   1492     result[7] = m24();
   1493     result[8] = m31();
   1494     result[9] = m32();
   1495     result[10] = m33();
   1496     result[11] = m34();
   1497     result[12] = m41();
   1498     result[13] = m42();
   1499     result[14] = m43();
   1500     result[15] = m44();
   1501 }
   1502 
   1503 bool TransformationMatrix::isBackFaceVisible() const
   1504 {
   1505     // Back-face visibility is determined by transforming the normal vector (0, 0, 1) and
   1506     // checking the sign of the resulting z component. However, normals cannot be
   1507     // transformed by the original matrix, they require being transformed by the
   1508     // inverse-transpose.
   1509     //
   1510     // Since we know we will be using (0, 0, 1), and we only care about the z-component of
   1511     // the transformed normal, then we only need the m33() element of the
   1512     // inverse-transpose. Therefore we do not need the transpose.
   1513     //
   1514     // Additionally, if we only need the m33() element, we do not need to compute a full
   1515     // inverse. Instead, knowing the inverse of a matrix is adjoint(matrix) / determinant,
   1516     // we can simply compute the m33() of the adjoint (adjugate) matrix, without computing
   1517     // the full adjoint.
   1518 
   1519     double determinant = WebCore::determinant4x4(m_matrix);
   1520 
   1521     // If the matrix is not invertible, then we assume its backface is not visible.
   1522     if (fabs(determinant) < SMALL_NUMBER)
   1523         return false;
   1524 
   1525     double cofactor33 = determinant3x3(m11(), m12(), m14(), m21(), m22(), m24(), m41(), m42(), m44());
   1526     double zComponentOfTransformedNormal = cofactor33 / determinant;
   1527 
   1528     return zComponentOfTransformedNormal < 0;
   1529 }
   1530 
   1531 }
   1532