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