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  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "TransformationMatrix.h"
     29 
     30 #include "AffineTransform.h"
     31 #include "FloatPoint3D.h"
     32 #include "FloatRect.h"
     33 #include "FloatQuad.h"
     34 #include "IntRect.h"
     35 
     36 #include <wtf/Assertions.h>
     37 #include <wtf/MathExtras.h>
     38 
     39 namespace WebCore {
     40 
     41 //
     42 // Supporting Math Functions
     43 //
     44 // This is a set of function from various places (attributed inline) to do things like
     45 // inversion and decomposition of a 4x4 matrix. They are used throughout the code
     46 //
     47 
     48 //
     49 // Adapted from Matrix Inversion by Richard Carling, Graphics Gems <http://tog.acm.org/GraphicsGems/index.html>.
     50 
     51 // EULA: The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code
     52 // as your own and resell it. Using the code is permitted in any program, product, or library, non-commercial
     53 // or commercial. Giving credit is not required, though is a nice gesture. The code comes as-is, and if there
     54 // are any flaws or problems with any Gems code, nobody involved with Gems - authors, editors, publishers, or
     55 // webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes
     56 // with no guarantee.
     57 
     58 // A clarification about the storage of matrix elements
     59 //
     60 // This class uses a 2 dimensional array internally to store the elements of the matrix.  The first index into
     61 // the array refers to the column that the element lies in; the second index refers to the row.
     62 //
     63 // In other words, this is the layout of the matrix:
     64 //
     65 // | m_matrix[0][0] m_matrix[1][0] m_matrix[2][0] m_matrix[3][0] |
     66 // | m_matrix[0][1] m_matrix[1][1] m_matrix[2][1] m_matrix[3][1] |
     67 // | m_matrix[0][2] m_matrix[1][2] m_matrix[2][2] m_matrix[3][2] |
     68 // | m_matrix[0][3] m_matrix[1][3] m_matrix[2][3] m_matrix[3][3] |
     69 
     70 typedef double Vector4[4];
     71 typedef double Vector3[3];
     72 
     73 const double SMALL_NUMBER = 1.e-8;
     74 
     75 // inverse(original_matrix, inverse_matrix)
     76 //
     77 // calculate the inverse of a 4x4 matrix
     78 //
     79 // -1
     80 // A  = ___1__ adjoint A
     81 //       det A
     82 
     83 //  double = determinant2x2(double a, double b, double c, double d)
     84 //
     85 //  calculate the determinant of a 2x2 matrix.
     86 
     87 static double determinant2x2(double a, double b, double c, double d)
     88 {
     89     return a * d - b * c;
     90 }
     91 
     92 //  double = determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3)
     93 //
     94 //  Calculate the determinant of a 3x3 matrix
     95 //  in the form
     96 //
     97 //      | a1,  b1,  c1 |
     98 //      | a2,  b2,  c2 |
     99 //      | a3,  b3,  c3 |
    100 
    101 static double determinant3x3(double a1, double a2, double a3, double b1, double b2, double b3, double c1, double c2, double c3)
    102 {
    103     return a1 * determinant2x2(b2, b3, c2, c3)
    104          - b1 * determinant2x2(a2, a3, c2, c3)
    105          + c1 * determinant2x2(a2, a3, b2, b3);
    106 }
    107 
    108 //  double = determinant4x4(matrix)
    109 //
    110 //  calculate the determinant of a 4x4 matrix.
    111 
    112 static double determinant4x4(const TransformationMatrix::Matrix4& m)
    113 {
    114     // Assign to individual variable names to aid selecting
    115     // correct elements
    116 
    117     double a1 = m[0][0];
    118     double b1 = m[0][1];
    119     double c1 = m[0][2];
    120     double d1 = m[0][3];
    121 
    122     double a2 = m[1][0];
    123     double b2 = m[1][1];
    124     double c2 = m[1][2];
    125     double d2 = m[1][3];
    126 
    127     double a3 = m[2][0];
    128     double b3 = m[2][1];
    129     double c3 = m[2][2];
    130     double d3 = m[2][3];
    131 
    132     double a4 = m[3][0];
    133     double b4 = m[3][1];
    134     double c4 = m[3][2];
    135     double d4 = m[3][3];
    136 
    137     return a1 * determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)
    138          - b1 * determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)
    139          + c1 * determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)
    140          - d1 * determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
    141 }
    142 
    143 // adjoint( original_matrix, inverse_matrix )
    144 //
    145 //   calculate the adjoint of a 4x4 matrix
    146 //
    147 //    Let  a   denote the minor determinant of matrix A obtained by
    148 //         ij
    149 //
    150 //    deleting the ith row and jth column from A.
    151 //
    152 //                  i+j
    153 //   Let  b   = (-1)    a
    154 //        ij            ji
    155 //
    156 //  The matrix B = (b  ) is the adjoint of A
    157 //                   ij
    158 
    159 static void adjoint(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Matrix4& result)
    160 {
    161     // Assign to individual variable names to aid
    162     // selecting correct values
    163     double a1 = matrix[0][0];
    164     double b1 = matrix[0][1];
    165     double c1 = matrix[0][2];
    166     double d1 = matrix[0][3];
    167 
    168     double a2 = matrix[1][0];
    169     double b2 = matrix[1][1];
    170     double c2 = matrix[1][2];
    171     double d2 = matrix[1][3];
    172 
    173     double a3 = matrix[2][0];
    174     double b3 = matrix[2][1];
    175     double c3 = matrix[2][2];
    176     double d3 = matrix[2][3];
    177 
    178     double a4 = matrix[3][0];
    179     double b4 = matrix[3][1];
    180     double c4 = matrix[3][2];
    181     double d4 = matrix[3][3];
    182 
    183     // Row column labeling reversed since we transpose rows & columns
    184     result[0][0]  =   determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
    185     result[1][0]  = - determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
    186     result[2][0]  =   determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
    187     result[3][0]  = - determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
    188 
    189     result[0][1]  = - determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
    190     result[1][1]  =   determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
    191     result[2][1]  = - determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
    192     result[3][1]  =   determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
    193 
    194     result[0][2]  =   determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
    195     result[1][2]  = - determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
    196     result[2][2]  =   determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
    197     result[3][2]  = - determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
    198 
    199     result[0][3]  = - determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
    200     result[1][3]  =   determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
    201     result[2][3]  = - determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
    202     result[3][3]  =   determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
    203 }
    204 
    205 // Returns false if the matrix is not invertible
    206 static bool inverse(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Matrix4& result)
    207 {
    208     // Calculate the adjoint matrix
    209     adjoint(matrix, result);
    210 
    211     // Calculate the 4x4 determinant
    212     // If the determinant is zero,
    213     // then the inverse matrix is not unique.
    214     double det = determinant4x4(matrix);
    215 
    216     if (fabs(det) < SMALL_NUMBER)
    217         return false;
    218 
    219     // Scale the adjoint matrix to get the inverse
    220 
    221     for (int i = 0; i < 4; i++)
    222         for (int j = 0; j < 4; j++)
    223             result[i][j] = result[i][j] / det;
    224 
    225     return true;
    226 }
    227 
    228 // End of code adapted from Matrix Inversion by Richard Carling
    229 
    230 // Perform a decomposition on the passed matrix, return false if unsuccessful
    231 // From Graphics Gems: unmatrix.c
    232 
    233 // Transpose rotation portion of matrix a, return b
    234 static void transposeMatrix4(const TransformationMatrix::Matrix4& a, TransformationMatrix::Matrix4& b)
    235 {
    236     for (int i = 0; i < 4; i++)
    237         for (int j = 0; j < 4; j++)
    238             b[i][j] = a[j][i];
    239 }
    240 
    241 // Multiply a homogeneous point by a matrix and return the transformed point
    242 static void v4MulPointByMatrix(const Vector4 p, const TransformationMatrix::Matrix4& m, Vector4 result)
    243 {
    244     result[0] = (p[0] * m[0][0]) + (p[1] * m[1][0]) +
    245                 (p[2] * m[2][0]) + (p[3] * m[3][0]);
    246     result[1] = (p[0] * m[0][1]) + (p[1] * m[1][1]) +
    247                 (p[2] * m[2][1]) + (p[3] * m[3][1]);
    248     result[2] = (p[0] * m[0][2]) + (p[1] * m[1][2]) +
    249                 (p[2] * m[2][2]) + (p[3] * m[3][2]);
    250     result[3] = (p[0] * m[0][3]) + (p[1] * m[1][3]) +
    251                 (p[2] * m[2][3]) + (p[3] * m[3][3]);
    252 }
    253 
    254 static double v3Length(Vector3 a)
    255 {
    256     return sqrt((a[0] * a[0]) + (a[1] * a[1]) + (a[2] * a[2]));
    257 }
    258 
    259 static void v3Scale(Vector3 v, double desiredLength)
    260 {
    261     double len = v3Length(v);
    262     if (len != 0) {
    263         double l = desiredLength / len;
    264         v[0] *= l;
    265         v[1] *= l;
    266         v[2] *= l;
    267     }
    268 }
    269 
    270 static double v3Dot(const Vector3 a, const Vector3 b)
    271 {
    272     return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
    273 }
    274 
    275 // Make a linear combination of two vectors and return the result.
    276 // result = (a * ascl) + (b * bscl)
    277 static void v3Combine(const Vector3 a, const Vector3 b, Vector3 result, double ascl, double bscl)
    278 {
    279     result[0] = (ascl * a[0]) + (bscl * b[0]);
    280     result[1] = (ascl * a[1]) + (bscl * b[1]);
    281     result[2] = (ascl * a[2]) + (bscl * b[2]);
    282 }
    283 
    284 // Return the cross product result = a cross b */
    285 static void v3Cross(const Vector3 a, const Vector3 b, Vector3 result)
    286 {
    287     result[0] = (a[1] * b[2]) - (a[2] * b[1]);
    288     result[1] = (a[2] * b[0]) - (a[0] * b[2]);
    289     result[2] = (a[0] * b[1]) - (a[1] * b[0]);
    290 }
    291 
    292 static bool decompose(const TransformationMatrix::Matrix4& mat, TransformationMatrix::DecomposedType& result)
    293 {
    294     TransformationMatrix::Matrix4 localMatrix;
    295     memcpy(localMatrix, mat, sizeof(TransformationMatrix::Matrix4));
    296 
    297     // Normalize the matrix.
    298     if (localMatrix[3][3] == 0)
    299         return false;
    300 
    301     int i, j;
    302     for (i = 0; i < 4; i++)
    303         for (j = 0; j < 4; j++)
    304             localMatrix[i][j] /= localMatrix[3][3];
    305 
    306     // perspectiveMatrix is used to solve for perspective, but it also provides
    307     // an easy way to test for singularity of the upper 3x3 component.
    308     TransformationMatrix::Matrix4 perspectiveMatrix;
    309     memcpy(perspectiveMatrix, localMatrix, sizeof(TransformationMatrix::Matrix4));
    310     for (i = 0; i < 3; i++)
    311         perspectiveMatrix[i][3] = 0;
    312     perspectiveMatrix[3][3] = 1;
    313 
    314     if (determinant4x4(perspectiveMatrix) == 0)
    315         return false;
    316 
    317     // First, isolate perspective.  This is the messiest.
    318     if (localMatrix[0][3] != 0 || localMatrix[1][3] != 0 || localMatrix[2][3] != 0) {
    319         // rightHandSide is the right hand side of the equation.
    320         Vector4 rightHandSide;
    321         rightHandSide[0] = localMatrix[0][3];
    322         rightHandSide[1] = localMatrix[1][3];
    323         rightHandSide[2] = localMatrix[2][3];
    324         rightHandSide[3] = localMatrix[3][3];
    325 
    326         // Solve the equation by inverting perspectiveMatrix and multiplying
    327         // rightHandSide by the inverse.  (This is the easiest way, not
    328         // necessarily the best.)
    329         TransformationMatrix::Matrix4 inversePerspectiveMatrix, transposedInversePerspectiveMatrix;
    330         inverse(perspectiveMatrix, inversePerspectiveMatrix);
    331         transposeMatrix4(inversePerspectiveMatrix, transposedInversePerspectiveMatrix);
    332 
    333         Vector4 perspectivePoint;
    334         v4MulPointByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspectivePoint);
    335 
    336         result.perspectiveX = perspectivePoint[0];
    337         result.perspectiveY = perspectivePoint[1];
    338         result.perspectiveZ = perspectivePoint[2];
    339         result.perspectiveW = perspectivePoint[3];
    340 
    341         // Clear the perspective partition
    342         localMatrix[0][3] = localMatrix[1][3] = localMatrix[2][3] = 0;
    343         localMatrix[3][3] = 1;
    344     } else {
    345         // No perspective.
    346         result.perspectiveX = result.perspectiveY = result.perspectiveZ = 0;
    347         result.perspectiveW = 1;
    348     }
    349 
    350     // Next take care of translation (easy).
    351     result.translateX = localMatrix[3][0];
    352     localMatrix[3][0] = 0;
    353     result.translateY = localMatrix[3][1];
    354     localMatrix[3][1] = 0;
    355     result.translateZ = localMatrix[3][2];
    356     localMatrix[3][2] = 0;
    357 
    358     // Vector4 type and functions need to be added to the common set.
    359     Vector3 row[3], pdum3;
    360 
    361     // Now get scale and shear.
    362     for (i = 0; i < 3; i++) {
    363         row[i][0] = localMatrix[i][0];
    364         row[i][1] = localMatrix[i][1];
    365         row[i][2] = localMatrix[i][2];
    366     }
    367 
    368     // Compute X scale factor and normalize first row.
    369     result.scaleX = v3Length(row[0]);
    370     v3Scale(row[0], 1.0);
    371 
    372     // Compute XY shear factor and make 2nd row orthogonal to 1st.
    373     result.skewXY = v3Dot(row[0], row[1]);
    374     v3Combine(row[1], row[0], row[1], 1.0, -result.skewXY);
    375 
    376     // Now, compute Y scale and normalize 2nd row.
    377     result.scaleY = v3Length(row[1]);
    378     v3Scale(row[1], 1.0);
    379     result.skewXY /= result.scaleY;
    380 
    381     // Compute XZ and YZ shears, orthogonalize 3rd row.
    382     result.skewXZ = v3Dot(row[0], row[2]);
    383     v3Combine(row[2], row[0], row[2], 1.0, -result.skewXZ);
    384     result.skewYZ = v3Dot(row[1], row[2]);
    385     v3Combine(row[2], row[1], row[2], 1.0, -result.skewYZ);
    386 
    387     // Next, get Z scale and normalize 3rd row.
    388     result.scaleZ = v3Length(row[2]);
    389     v3Scale(row[2], 1.0);
    390     result.skewXZ /= result.scaleZ;
    391     result.skewYZ /= result.scaleZ;
    392 
    393     // At this point, the matrix (in rows[]) is orthonormal.
    394     // Check for a coordinate system flip.  If the determinant
    395     // is -1, then negate the matrix and the scaling factors.
    396     v3Cross(row[1], row[2], pdum3);
    397     if (v3Dot(row[0], pdum3) < 0) {
    398         for (i = 0; i < 3; i++) {
    399             result.scaleX *= -1;
    400             row[i][0] *= -1;
    401             row[i][1] *= -1;
    402             row[i][2] *= -1;
    403         }
    404     }
    405 
    406     // Now, get the rotations out, as described in the gem.
    407 
    408     // FIXME - Add the ability to return either quaternions (which are
    409     // easier to recompose with) or Euler angles (rx, ry, rz), which
    410     // are easier for authors to deal with. The latter will only be useful
    411     // when we fix https://bugs.webkit.org/show_bug.cgi?id=23799, so I
    412     // will leave the Euler angle code here for now.
    413 
    414     // ret.rotateY = asin(-row[0][2]);
    415     // if (cos(ret.rotateY) != 0) {
    416     //     ret.rotateX = atan2(row[1][2], row[2][2]);
    417     //     ret.rotateZ = atan2(row[0][1], row[0][0]);
    418     // } else {
    419     //     ret.rotateX = atan2(-row[2][0], row[1][1]);
    420     //     ret.rotateZ = 0;
    421     // }
    422 
    423     double s, t, x, y, z, w;
    424 
    425     t = row[0][0] + row[1][1] + row[2][2] + 1.0;
    426 
    427     if (t > 1e-4) {
    428         s = 0.5 / sqrt(t);
    429         w = 0.25 / s;
    430         x = (row[2][1] - row[1][2]) * s;
    431         y = (row[0][2] - row[2][0]) * s;
    432         z = (row[1][0] - row[0][1]) * s;
    433     } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) {
    434         s = sqrt (1.0 + row[0][0] - row[1][1] - row[2][2]) * 2.0; // S=4*qx
    435         x = 0.25 * s;
    436         y = (row[0][1] + row[1][0]) / s;
    437         z = (row[0][2] + row[2][0]) / s;
    438         w = (row[2][1] - row[1][2]) / s;
    439     } else if (row[1][1] > row[2][2]) {
    440         s = sqrt (1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; // S=4*qy
    441         x = (row[0][1] + row[1][0]) / s;
    442         y = 0.25 * s;
    443         z = (row[1][2] + row[2][1]) / s;
    444         w = (row[0][2] - row[2][0]) / s;
    445     } else {
    446         s = sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; // S=4*qz
    447         x = (row[0][2] + row[2][0]) / s;
    448         y = (row[1][2] + row[2][1]) / s;
    449         z = 0.25 * s;
    450         w = (row[1][0] - row[0][1]) / s;
    451     }
    452 
    453     result.quaternionX = x;
    454     result.quaternionY = y;
    455     result.quaternionZ = z;
    456     result.quaternionW = w;
    457 
    458     return true;
    459 }
    460 
    461 // Perform a spherical linear interpolation between the two
    462 // passed quaternions with 0 <= t <= 1
    463 static void slerp(double qa[4], const double qb[4], double t)
    464 {
    465     double ax, ay, az, aw;
    466     double bx, by, bz, bw;
    467     double cx, cy, cz, cw;
    468     double angle;
    469     double th, invth, scale, invscale;
    470 
    471     ax = qa[0]; ay = qa[1]; az = qa[2]; aw = qa[3];
    472     bx = qb[0]; by = qb[1]; bz = qb[2]; bw = qb[3];
    473 
    474     angle = ax * bx + ay * by + az * bz + aw * bw;
    475 
    476     if (angle < 0.0) {
    477         ax = -ax; ay = -ay;
    478         az = -az; aw = -aw;
    479         angle = -angle;
    480     }
    481 
    482     if (angle + 1.0 > .05) {
    483         if (1.0 - angle >= .05) {
    484             th = acos (angle);
    485             invth = 1.0 / sin (th);
    486             scale = sin (th * (1.0 - t)) * invth;
    487             invscale = sin (th * t) * invth;
    488         } else {
    489             scale = 1.0 - t;
    490             invscale = t;
    491         }
    492     } else {
    493         bx = -ay;
    494         by = ax;
    495         bz = -aw;
    496         bw = az;
    497         scale = sin(piDouble * (.5 - t));
    498         invscale = sin (piDouble * t);
    499     }
    500 
    501     cx = ax * scale + bx * invscale;
    502     cy = ay * scale + by * invscale;
    503     cz = az * scale + bz * invscale;
    504     cw = aw * scale + bw * invscale;
    505 
    506     qa[0] = cx; qa[1] = cy; qa[2] = cz; qa[3] = cw;
    507 }
    508 
    509 // End of Supporting Math Functions
    510 
    511 TransformationMatrix& TransformationMatrix::scale(double s)
    512 {
    513     return scaleNonUniform(s, s);
    514 }
    515 
    516 TransformationMatrix& TransformationMatrix::rotateFromVector(double x, double y)
    517 {
    518     return rotate(rad2deg(atan2(y, x)));
    519 }
    520 
    521 TransformationMatrix& TransformationMatrix::flipX()
    522 {
    523     return scaleNonUniform(-1.0f, 1.0f);
    524 }
    525 
    526 TransformationMatrix& TransformationMatrix::flipY()
    527 {
    528     return scaleNonUniform(1.0f, -1.0f);
    529 }
    530 
    531 FloatPoint TransformationMatrix::projectPoint(const FloatPoint& p) const
    532 {
    533     // This is basically raytracing. We have a point in the destination
    534     // plane with z=0, and we cast a ray parallel to the z-axis from that
    535     // point to find the z-position at which it intersects the z=0 plane
    536     // with the transform applied. Once we have that point we apply the
    537     // inverse transform to find the corresponding point in the source
    538     // space.
    539     //
    540     // Given a plane with normal Pn, and a ray starting at point R0 and
    541     // with direction defined by the vector Rd, we can find the
    542     // intersection point as a distance d from R0 in units of Rd by:
    543     //
    544     // d = -dot (Pn', R0) / dot (Pn', Rd)
    545 
    546     double x = p.x();
    547     double y = p.y();
    548     double z = -(m13() * x + m23() * y + m43()) / m33();
    549 
    550     double outX = x * m11() + y * m21() + z * m31() + m41();
    551     double outY = x * m12() + y * m22() + z * m32() + m42();
    552 
    553     double w = x * m14() + y * m24() + z * m34() + m44();
    554     if (w != 1 && w != 0) {
    555         outX /= w;
    556         outY /= w;
    557     }
    558 
    559     return FloatPoint(static_cast<float>(outX), static_cast<float>(outY));
    560 }
    561 
    562 FloatQuad TransformationMatrix::projectQuad(const FloatQuad& q) const
    563 {
    564     FloatQuad projectedQuad;
    565     projectedQuad.setP1(projectPoint(q.p1()));
    566     projectedQuad.setP2(projectPoint(q.p2()));
    567     projectedQuad.setP3(projectPoint(q.p3()));
    568     projectedQuad.setP4(projectPoint(q.p4()));
    569     return projectedQuad;
    570 }
    571 
    572 FloatPoint TransformationMatrix::mapPoint(const FloatPoint& p) const
    573 {
    574     if (isIdentityOrTranslation())
    575         return FloatPoint(p.x() + static_cast<float>(m_matrix[3][0]), p.y() + static_cast<float>(m_matrix[3][1]));
    576 
    577     double x, y;
    578     multVecMatrix(p.x(), p.y(), x, y);
    579     return FloatPoint(static_cast<float>(x), static_cast<float>(y));
    580 }
    581 
    582 FloatPoint3D TransformationMatrix::mapPoint(const FloatPoint3D& p) const
    583 {
    584     if (isIdentityOrTranslation())
    585         return FloatPoint3D(p.x() + static_cast<float>(m_matrix[3][0]),
    586                             p.y() + static_cast<float>(m_matrix[3][1]),
    587                             p.z() + static_cast<float>(m_matrix[3][2]));
    588 
    589     double x, y, z;
    590     multVecMatrix(p.x(), p.y(), p.z(), x, y, z);
    591     return FloatPoint3D(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));
    592 }
    593 
    594 IntRect TransformationMatrix::mapRect(const IntRect &rect) const
    595 {
    596     return enclosingIntRect(mapRect(FloatRect(rect)));
    597 }
    598 
    599 FloatRect TransformationMatrix::mapRect(const FloatRect& r) const
    600 {
    601     if (isIdentityOrTranslation()) {
    602         FloatRect mappedRect(r);
    603         mappedRect.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
    604         return mappedRect;
    605     }
    606 
    607     FloatQuad resultQuad = mapQuad(FloatQuad(r));
    608     return resultQuad.boundingBox();
    609 }
    610 
    611 FloatQuad TransformationMatrix::mapQuad(const FloatQuad& q) const
    612 {
    613     if (isIdentityOrTranslation()) {
    614         FloatQuad mappedQuad(q);
    615         mappedQuad.move(static_cast<float>(m_matrix[3][0]), static_cast<float>(m_matrix[3][1]));
    616         return mappedQuad;
    617     }
    618 
    619     FloatQuad result;
    620     result.setP1(mapPoint(q.p1()));
    621     result.setP2(mapPoint(q.p2()));
    622     result.setP3(mapPoint(q.p3()));
    623     result.setP4(mapPoint(q.p4()));
    624     return result;
    625 }
    626 
    627 TransformationMatrix& TransformationMatrix::scaleNonUniform(double sx, double sy)
    628 {
    629     TransformationMatrix mat;
    630     mat.m_matrix[0][0] = sx;
    631     mat.m_matrix[1][1] = sy;
    632 
    633     multiply(mat);
    634     return *this;
    635 }
    636 
    637 TransformationMatrix& TransformationMatrix::scale3d(double sx, double sy, double sz)
    638 {
    639     TransformationMatrix mat;
    640     mat.m_matrix[0][0] = sx;
    641     mat.m_matrix[1][1] = sy;
    642     mat.m_matrix[2][2] = sz;
    643 
    644     multiply(mat);
    645     return *this;
    646 }
    647 
    648 TransformationMatrix& TransformationMatrix::rotate3d(double x, double y, double z, double angle)
    649 {
    650     // angles are in degrees. Switch to radians
    651     angle = deg2rad(angle);
    652 
    653     angle /= 2.0f;
    654     double sinA = sin(angle);
    655     double cosA = cos(angle);
    656     double sinA2 = sinA * sinA;
    657 
    658     // normalize
    659     double length = sqrt(x * x + y * y + z * z);
    660     if (length == 0) {
    661         // bad vector, just use something reasonable
    662         x = 0;
    663         y = 0;
    664         z = 1;
    665     } else if (length != 1) {
    666         x /= length;
    667         y /= length;
    668         z /= length;
    669     }
    670 
    671     TransformationMatrix mat;
    672 
    673     // optimize case where axis is along major axis
    674     if (x == 1.0f && y == 0.0f && z == 0.0f) {
    675         mat.m_matrix[0][0] = 1.0f;
    676         mat.m_matrix[0][1] = 0.0f;
    677         mat.m_matrix[0][2] = 0.0f;
    678         mat.m_matrix[1][0] = 0.0f;
    679         mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2;
    680         mat.m_matrix[1][2] = 2.0f * sinA * cosA;
    681         mat.m_matrix[2][0] = 0.0f;
    682         mat.m_matrix[2][1] = -2.0f * sinA * cosA;
    683         mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2;
    684         mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
    685         mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
    686         mat.m_matrix[3][3] = 1.0f;
    687     } else if (x == 0.0f && y == 1.0f && z == 0.0f) {
    688         mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2;
    689         mat.m_matrix[0][1] = 0.0f;
    690         mat.m_matrix[0][2] = -2.0f * sinA * cosA;
    691         mat.m_matrix[1][0] = 0.0f;
    692         mat.m_matrix[1][1] = 1.0f;
    693         mat.m_matrix[1][2] = 0.0f;
    694         mat.m_matrix[2][0] = 2.0f * sinA * cosA;
    695         mat.m_matrix[2][1] = 0.0f;
    696         mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2;
    697         mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
    698         mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
    699         mat.m_matrix[3][3] = 1.0f;
    700     } else if (x == 0.0f && y == 0.0f && z == 1.0f) {
    701         mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2;
    702         mat.m_matrix[0][1] = 2.0f * sinA * cosA;
    703         mat.m_matrix[0][2] = 0.0f;
    704         mat.m_matrix[1][0] = -2.0f * sinA * cosA;
    705         mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2;
    706         mat.m_matrix[1][2] = 0.0f;
    707         mat.m_matrix[2][0] = 0.0f;
    708         mat.m_matrix[2][1] = 0.0f;
    709         mat.m_matrix[2][2] = 1.0f;
    710         mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
    711         mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
    712         mat.m_matrix[3][3] = 1.0f;
    713     } else {
    714         double x2 = x*x;
    715         double y2 = y*y;
    716         double z2 = z*z;
    717 
    718         mat.m_matrix[0][0] = 1.0f - 2.0f * (y2 + z2) * sinA2;
    719         mat.m_matrix[0][1] = 2.0f * (x * y * sinA2 + z * sinA * cosA);
    720         mat.m_matrix[0][2] = 2.0f * (x * z * sinA2 - y * sinA * cosA);
    721         mat.m_matrix[1][0] = 2.0f * (y * x * sinA2 - z * sinA * cosA);
    722         mat.m_matrix[1][1] = 1.0f - 2.0f * (z2 + x2) * sinA2;
    723         mat.m_matrix[1][2] = 2.0f * (y * z * sinA2 + x * sinA * cosA);
    724         mat.m_matrix[2][0] = 2.0f * (z * x * sinA2 + y * sinA * cosA);
    725         mat.m_matrix[2][1] = 2.0f * (z * y * sinA2 - x * sinA * cosA);
    726         mat.m_matrix[2][2] = 1.0f - 2.0f * (x2 + y2) * sinA2;
    727         mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
    728         mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
    729         mat.m_matrix[3][3] = 1.0f;
    730     }
    731     multiply(mat);
    732     return *this;
    733 }
    734 
    735 TransformationMatrix& TransformationMatrix::rotate3d(double rx, double ry, double rz)
    736 {
    737     // angles are in degrees. Switch to radians
    738     rx = deg2rad(rx);
    739     ry = deg2rad(ry);
    740     rz = deg2rad(rz);
    741 
    742     TransformationMatrix mat;
    743 
    744     rz /= 2.0f;
    745     double sinA = sin(rz);
    746     double cosA = cos(rz);
    747     double sinA2 = sinA * sinA;
    748 
    749     mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2;
    750     mat.m_matrix[0][1] = 2.0f * sinA * cosA;
    751     mat.m_matrix[0][2] = 0.0f;
    752     mat.m_matrix[1][0] = -2.0f * sinA * cosA;
    753     mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2;
    754     mat.m_matrix[1][2] = 0.0f;
    755     mat.m_matrix[2][0] = 0.0f;
    756     mat.m_matrix[2][1] = 0.0f;
    757     mat.m_matrix[2][2] = 1.0f;
    758     mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
    759     mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
    760     mat.m_matrix[3][3] = 1.0f;
    761 
    762     TransformationMatrix rmat(mat);
    763 
    764     ry /= 2.0f;
    765     sinA = sin(ry);
    766     cosA = cos(ry);
    767     sinA2 = sinA * sinA;
    768 
    769     mat.m_matrix[0][0] = 1.0f - 2.0f * sinA2;
    770     mat.m_matrix[0][1] = 0.0f;
    771     mat.m_matrix[0][2] = -2.0f * sinA * cosA;
    772     mat.m_matrix[1][0] = 0.0f;
    773     mat.m_matrix[1][1] = 1.0f;
    774     mat.m_matrix[1][2] = 0.0f;
    775     mat.m_matrix[2][0] = 2.0f * sinA * cosA;
    776     mat.m_matrix[2][1] = 0.0f;
    777     mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2;
    778     mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
    779     mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
    780     mat.m_matrix[3][3] = 1.0f;
    781 
    782     rmat.multiply(mat);
    783 
    784     rx /= 2.0f;
    785     sinA = sin(rx);
    786     cosA = cos(rx);
    787     sinA2 = sinA * sinA;
    788 
    789     mat.m_matrix[0][0] = 1.0f;
    790     mat.m_matrix[0][1] = 0.0f;
    791     mat.m_matrix[0][2] = 0.0f;
    792     mat.m_matrix[1][0] = 0.0f;
    793     mat.m_matrix[1][1] = 1.0f - 2.0f * sinA2;
    794     mat.m_matrix[1][2] = 2.0f * sinA * cosA;
    795     mat.m_matrix[2][0] = 0.0f;
    796     mat.m_matrix[2][1] = -2.0f * sinA * cosA;
    797     mat.m_matrix[2][2] = 1.0f - 2.0f * sinA2;
    798     mat.m_matrix[0][3] = mat.m_matrix[1][3] = mat.m_matrix[2][3] = 0.0f;
    799     mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0f;
    800     mat.m_matrix[3][3] = 1.0f;
    801 
    802     rmat.multiply(mat);
    803 
    804     multiply(rmat);
    805     return *this;
    806 }
    807 
    808 TransformationMatrix& TransformationMatrix::translate(double tx, double ty)
    809 {
    810     m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0];
    811     m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1];
    812     m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2];
    813     m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3];
    814     return *this;
    815 }
    816 
    817 TransformationMatrix& TransformationMatrix::translate3d(double tx, double ty, double tz)
    818 {
    819     m_matrix[3][0] += tx * m_matrix[0][0] + ty * m_matrix[1][0] + tz * m_matrix[2][0];
    820     m_matrix[3][1] += tx * m_matrix[0][1] + ty * m_matrix[1][1] + tz * m_matrix[2][1];
    821     m_matrix[3][2] += tx * m_matrix[0][2] + ty * m_matrix[1][2] + tz * m_matrix[2][2];
    822     m_matrix[3][3] += tx * m_matrix[0][3] + ty * m_matrix[1][3] + tz * m_matrix[2][3];
    823     return *this;
    824 }
    825 
    826 TransformationMatrix& TransformationMatrix::translateRight(double tx, double ty)
    827 {
    828     if (tx != 0) {
    829         m_matrix[0][0] +=  m_matrix[0][3] * tx;
    830         m_matrix[1][0] +=  m_matrix[1][3] * tx;
    831         m_matrix[2][0] +=  m_matrix[2][3] * tx;
    832         m_matrix[3][0] +=  m_matrix[3][3] * tx;
    833     }
    834 
    835     if (ty != 0) {
    836         m_matrix[0][1] +=  m_matrix[0][3] * ty;
    837         m_matrix[1][1] +=  m_matrix[1][3] * ty;
    838         m_matrix[2][1] +=  m_matrix[2][3] * ty;
    839         m_matrix[3][1] +=  m_matrix[3][3] * ty;
    840     }
    841 
    842     return *this;
    843 }
    844 
    845 TransformationMatrix& TransformationMatrix::translateRight3d(double tx, double ty, double tz)
    846 {
    847     translateRight(tx, ty);
    848     if (tz != 0) {
    849         m_matrix[0][2] +=  m_matrix[0][3] * tz;
    850         m_matrix[1][2] +=  m_matrix[1][3] * tz;
    851         m_matrix[2][2] +=  m_matrix[2][3] * tz;
    852         m_matrix[3][2] +=  m_matrix[3][3] * tz;
    853     }
    854 
    855     return *this;
    856 }
    857 
    858 TransformationMatrix& TransformationMatrix::skew(double sx, double sy)
    859 {
    860     // angles are in degrees. Switch to radians
    861     sx = deg2rad(sx);
    862     sy = deg2rad(sy);
    863 
    864     TransformationMatrix mat;
    865     mat.m_matrix[0][1] = tan(sy); // note that the y shear goes in the first row
    866     mat.m_matrix[1][0] = tan(sx); // and the x shear in the second row
    867 
    868     multiply(mat);
    869     return *this;
    870 }
    871 
    872 TransformationMatrix& TransformationMatrix::applyPerspective(double p)
    873 {
    874     TransformationMatrix mat;
    875     if (p != 0)
    876         mat.m_matrix[2][3] = -1/p;
    877 
    878     multiply(mat);
    879     return *this;
    880 }
    881 
    882 TransformationMatrix TransformationMatrix::rectToRect(const FloatRect& from, const FloatRect& to)
    883 {
    884     ASSERT(!from.isEmpty());
    885     return TransformationMatrix(to.width() / from.width(),
    886                                 0, 0,
    887                                 to.height() / from.height(),
    888                                 to.x() - from.x(),
    889                                 to.y() - from.y());
    890 }
    891 
    892 //
    893 // *this = mat * *this
    894 //
    895 TransformationMatrix& TransformationMatrix::multiply(const TransformationMatrix& mat)
    896 {
    897     Matrix4 tmp;
    898 
    899     tmp[0][0] = (mat.m_matrix[0][0] * m_matrix[0][0] + mat.m_matrix[0][1] * m_matrix[1][0]
    900                + mat.m_matrix[0][2] * m_matrix[2][0] + mat.m_matrix[0][3] * m_matrix[3][0]);
    901     tmp[0][1] = (mat.m_matrix[0][0] * m_matrix[0][1] + mat.m_matrix[0][1] * m_matrix[1][1]
    902                + mat.m_matrix[0][2] * m_matrix[2][1] + mat.m_matrix[0][3] * m_matrix[3][1]);
    903     tmp[0][2] = (mat.m_matrix[0][0] * m_matrix[0][2] + mat.m_matrix[0][1] * m_matrix[1][2]
    904                + mat.m_matrix[0][2] * m_matrix[2][2] + mat.m_matrix[0][3] * m_matrix[3][2]);
    905     tmp[0][3] = (mat.m_matrix[0][0] * m_matrix[0][3] + mat.m_matrix[0][1] * m_matrix[1][3]
    906                + mat.m_matrix[0][2] * m_matrix[2][3] + mat.m_matrix[0][3] * m_matrix[3][3]);
    907 
    908     tmp[1][0] = (mat.m_matrix[1][0] * m_matrix[0][0] + mat.m_matrix[1][1] * m_matrix[1][0]
    909                + mat.m_matrix[1][2] * m_matrix[2][0] + mat.m_matrix[1][3] * m_matrix[3][0]);
    910     tmp[1][1] = (mat.m_matrix[1][0] * m_matrix[0][1] + mat.m_matrix[1][1] * m_matrix[1][1]
    911                + mat.m_matrix[1][2] * m_matrix[2][1] + mat.m_matrix[1][3] * m_matrix[3][1]);
    912     tmp[1][2] = (mat.m_matrix[1][0] * m_matrix[0][2] + mat.m_matrix[1][1] * m_matrix[1][2]
    913                + mat.m_matrix[1][2] * m_matrix[2][2] + mat.m_matrix[1][3] * m_matrix[3][2]);
    914     tmp[1][3] = (mat.m_matrix[1][0] * m_matrix[0][3] + mat.m_matrix[1][1] * m_matrix[1][3]
    915                + mat.m_matrix[1][2] * m_matrix[2][3] + mat.m_matrix[1][3] * m_matrix[3][3]);
    916 
    917     tmp[2][0] = (mat.m_matrix[2][0] * m_matrix[0][0] + mat.m_matrix[2][1] * m_matrix[1][0]
    918                + mat.m_matrix[2][2] * m_matrix[2][0] + mat.m_matrix[2][3] * m_matrix[3][0]);
    919     tmp[2][1] = (mat.m_matrix[2][0] * m_matrix[0][1] + mat.m_matrix[2][1] * m_matrix[1][1]
    920                + mat.m_matrix[2][2] * m_matrix[2][1] + mat.m_matrix[2][3] * m_matrix[3][1]);
    921     tmp[2][2] = (mat.m_matrix[2][0] * m_matrix[0][2] + mat.m_matrix[2][1] * m_matrix[1][2]
    922                + mat.m_matrix[2][2] * m_matrix[2][2] + mat.m_matrix[2][3] * m_matrix[3][2]);
    923     tmp[2][3] = (mat.m_matrix[2][0] * m_matrix[0][3] + mat.m_matrix[2][1] * m_matrix[1][3]
    924                + mat.m_matrix[2][2] * m_matrix[2][3] + mat.m_matrix[2][3] * m_matrix[3][3]);
    925 
    926     tmp[3][0] = (mat.m_matrix[3][0] * m_matrix[0][0] + mat.m_matrix[3][1] * m_matrix[1][0]
    927                + mat.m_matrix[3][2] * m_matrix[2][0] + mat.m_matrix[3][3] * m_matrix[3][0]);
    928     tmp[3][1] = (mat.m_matrix[3][0] * m_matrix[0][1] + mat.m_matrix[3][1] * m_matrix[1][1]
    929                + mat.m_matrix[3][2] * m_matrix[2][1] + mat.m_matrix[3][3] * m_matrix[3][1]);
    930     tmp[3][2] = (mat.m_matrix[3][0] * m_matrix[0][2] + mat.m_matrix[3][1] * m_matrix[1][2]
    931                + mat.m_matrix[3][2] * m_matrix[2][2] + mat.m_matrix[3][3] * m_matrix[3][2]);
    932     tmp[3][3] = (mat.m_matrix[3][0] * m_matrix[0][3] + mat.m_matrix[3][1] * m_matrix[1][3]
    933                + mat.m_matrix[3][2] * m_matrix[2][3] + mat.m_matrix[3][3] * m_matrix[3][3]);
    934 
    935     setMatrix(tmp);
    936     return *this;
    937 }
    938 
    939 void TransformationMatrix::multVecMatrix(double x, double y, double& resultX, double& resultY) const
    940 {
    941     resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0];
    942     resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1];
    943     double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3];
    944     if (w != 1 && w != 0) {
    945         resultX /= w;
    946         resultY /= w;
    947     }
    948 }
    949 
    950 void TransformationMatrix::multVecMatrix(double x, double y, double z, double& resultX, double& resultY, double& resultZ) const
    951 {
    952     resultX = m_matrix[3][0] + x * m_matrix[0][0] + y * m_matrix[1][0] + z * m_matrix[2][0];
    953     resultY = m_matrix[3][1] + x * m_matrix[0][1] + y * m_matrix[1][1] + z * m_matrix[2][1];
    954     resultZ = m_matrix[3][2] + x * m_matrix[0][2] + y * m_matrix[1][2] + z * m_matrix[2][2];
    955     double w = m_matrix[3][3] + x * m_matrix[0][3] + y * m_matrix[1][3] + z * m_matrix[2][3];
    956     if (w != 1 && w != 0) {
    957         resultX /= w;
    958         resultY /= w;
    959         resultZ /= w;
    960     }
    961 }
    962 
    963 bool TransformationMatrix::isInvertible() const
    964 {
    965     if (isIdentityOrTranslation())
    966         return true;
    967 
    968     double det = WebCore::determinant4x4(m_matrix);
    969 
    970     if (fabs(det) < SMALL_NUMBER)
    971         return false;
    972 
    973     return true;
    974 }
    975 
    976 TransformationMatrix TransformationMatrix::inverse() const
    977 {
    978     if (isIdentityOrTranslation()) {
    979         // identity matrix
    980         if (m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0)
    981             return TransformationMatrix();
    982 
    983         // translation
    984         return TransformationMatrix(1, 0, 0, 0,
    985                                     0, 1, 0, 0,
    986                                     0, 0, 1, 0,
    987                                     -m_matrix[3][0], -m_matrix[3][1], -m_matrix[3][2], 1);
    988     }
    989 
    990     TransformationMatrix invMat;
    991     bool inverted = WebCore::inverse(m_matrix, invMat.m_matrix);
    992     if (!inverted)
    993         return TransformationMatrix();
    994 
    995     return invMat;
    996 }
    997 
    998 void TransformationMatrix::makeAffine()
    999 {
   1000     m_matrix[0][2] = 0;
   1001     m_matrix[0][3] = 0;
   1002 
   1003     m_matrix[1][2] = 0;
   1004     m_matrix[1][3] = 0;
   1005 
   1006     m_matrix[2][0] = 0;
   1007     m_matrix[2][1] = 0;
   1008     m_matrix[2][2] = 1;
   1009     m_matrix[2][3] = 0;
   1010 
   1011     m_matrix[3][2] = 0;
   1012     m_matrix[3][3] = 1;
   1013 }
   1014 
   1015 AffineTransform TransformationMatrix::toAffineTransform() const
   1016 {
   1017     return AffineTransform(m_matrix[0][0], m_matrix[0][1], m_matrix[1][0],
   1018                            m_matrix[1][1], m_matrix[3][0], m_matrix[3][1]);
   1019 }
   1020 
   1021 static inline void blendFloat(double& from, double to, double progress)
   1022 {
   1023     if (from != to)
   1024         from = from + (to - from) * progress;
   1025 }
   1026 
   1027 void TransformationMatrix::blend(const TransformationMatrix& from, double progress)
   1028 {
   1029     if (from.isIdentity() && isIdentity())
   1030         return;
   1031 
   1032     // decompose
   1033     DecomposedType fromDecomp;
   1034     DecomposedType toDecomp;
   1035     from.decompose(fromDecomp);
   1036     decompose(toDecomp);
   1037 
   1038     // interpolate
   1039     blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress);
   1040     blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress);
   1041     blendFloat(fromDecomp.scaleZ, toDecomp.scaleZ, progress);
   1042     blendFloat(fromDecomp.skewXY, toDecomp.skewXY, progress);
   1043     blendFloat(fromDecomp.skewXZ, toDecomp.skewXZ, progress);
   1044     blendFloat(fromDecomp.skewYZ, toDecomp.skewYZ, progress);
   1045     blendFloat(fromDecomp.translateX, toDecomp.translateX, progress);
   1046     blendFloat(fromDecomp.translateY, toDecomp.translateY, progress);
   1047     blendFloat(fromDecomp.translateZ, toDecomp.translateZ, progress);
   1048     blendFloat(fromDecomp.perspectiveX, toDecomp.perspectiveX, progress);
   1049     blendFloat(fromDecomp.perspectiveY, toDecomp.perspectiveY, progress);
   1050     blendFloat(fromDecomp.perspectiveZ, toDecomp.perspectiveZ, progress);
   1051     blendFloat(fromDecomp.perspectiveW, toDecomp.perspectiveW, progress);
   1052 
   1053     slerp(&fromDecomp.quaternionX, &toDecomp.quaternionX, progress);
   1054 
   1055     // recompose
   1056     recompose(fromDecomp);
   1057 }
   1058 
   1059 bool TransformationMatrix::decompose(DecomposedType& decomp) const
   1060 {
   1061     if (isIdentity()) {
   1062         memset(&decomp, 0, sizeof(decomp));
   1063         decomp.perspectiveW = 1;
   1064         decomp.scaleX = 1;
   1065         decomp.scaleY = 1;
   1066         decomp.scaleZ = 1;
   1067     }
   1068 
   1069     if (!WebCore::decompose(m_matrix, decomp))
   1070         return false;
   1071     return true;
   1072 }
   1073 
   1074 void TransformationMatrix::recompose(const DecomposedType& decomp)
   1075 {
   1076     makeIdentity();
   1077 
   1078     // first apply perspective
   1079     m_matrix[0][3] = (float) decomp.perspectiveX;
   1080     m_matrix[1][3] = (float) decomp.perspectiveY;
   1081     m_matrix[2][3] = (float) decomp.perspectiveZ;
   1082     m_matrix[3][3] = (float) decomp.perspectiveW;
   1083 
   1084     // now translate
   1085     translate3d((float) decomp.translateX, (float) decomp.translateY, (float) decomp.translateZ);
   1086 
   1087     // apply rotation
   1088     double xx = decomp.quaternionX * decomp.quaternionX;
   1089     double xy = decomp.quaternionX * decomp.quaternionY;
   1090     double xz = decomp.quaternionX * decomp.quaternionZ;
   1091     double xw = decomp.quaternionX * decomp.quaternionW;
   1092     double yy = decomp.quaternionY * decomp.quaternionY;
   1093     double yz = decomp.quaternionY * decomp.quaternionZ;
   1094     double yw = decomp.quaternionY * decomp.quaternionW;
   1095     double zz = decomp.quaternionZ * decomp.quaternionZ;
   1096     double zw = decomp.quaternionZ * decomp.quaternionW;
   1097 
   1098     // Construct a composite rotation matrix from the quaternion values
   1099     TransformationMatrix rotationMatrix(1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0,
   1100                            2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0,
   1101                            2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0,
   1102                            0, 0, 0, 1);
   1103 
   1104     multiply(rotationMatrix);
   1105 
   1106     // now apply skew
   1107     if (decomp.skewYZ) {
   1108         TransformationMatrix tmp;
   1109         tmp.setM32((float) decomp.skewYZ);
   1110         multiply(tmp);
   1111     }
   1112 
   1113     if (decomp.skewXZ) {
   1114         TransformationMatrix tmp;
   1115         tmp.setM31((float) decomp.skewXZ);
   1116         multiply(tmp);
   1117     }
   1118 
   1119     if (decomp.skewXY) {
   1120         TransformationMatrix tmp;
   1121         tmp.setM21((float) decomp.skewXY);
   1122         multiply(tmp);
   1123     }
   1124 
   1125     // finally, apply scale
   1126     scale3d((float) decomp.scaleX, (float) decomp.scaleY, (float) decomp.scaleZ);
   1127 }
   1128 
   1129 }
   1130