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