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