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 "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
29 
30 #include <cmath>
31 #include <cstdlib>
32 
33 #include "base/compiler_specific.h"
34 #include "third_party/blink/renderer/platform/geometry/float_box.h"
35 #include "third_party/blink/renderer/platform/geometry/float_quad.h"
36 #include "third_party/blink/renderer/platform/geometry/float_rect.h"
37 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
38 #include "third_party/blink/renderer/platform/geometry/layout_rect.h"
39 #include "third_party/blink/renderer/platform/json/json_values.h"
40 #include "third_party/blink/renderer/platform/transforms/affine_transform.h"
41 #include "third_party/blink/renderer/platform/transforms/rotation.h"
42 #include "third_party/blink/renderer/platform/wtf/assertions.h"
43 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
44 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
45 #include "ui/gfx/geometry/quaternion.h"
46 #include "ui/gfx/transform.h"
47 
48 #if defined(ARCH_CPU_X86_64)
49 #include <emmintrin.h>
50 #endif
51 
52 #if defined(HAVE_MIPS_MSA_INTRINSICS)
53 #include "third_party/blink/renderer/platform/cpu/mips/common_macros_msa.h"
54 #endif
55 
56 namespace blink {
57 
58 using gfx::Quaternion;
59 
60 //
61 // Supporting Math Functions
62 //
63 // This is a set of function from various places (attributed inline) to do
64 // things like inversion and decomposition of a 4x4 matrix. They are used
65 // throughout the code
66 //
67 
68 //
69 // Adapted from Matrix Inversion by Richard Carling, Graphics Gems
70 // <http://tog.acm.org/GraphicsGems/index.html>.
71 
72 // EULA: The Graphics Gems code is copyright-protected. In other words, you
73 // cannot claim the text of the code as your own and resell it. Using the code
74 // is permitted in any program, product, or library, non-commercial or
75 // commercial. Giving credit is not required, though is a nice gesture. The code
76 // comes as-is, and if there are any flaws or problems with any Gems code,
77 // nobody involved with Gems - authors, editors, publishers, or webmasters - are
78 // to be held responsible. Basically, don't be a jerk, and remember that
79 // anything free comes with no guarantee.
80 
81 typedef double Vector4[4];
82 typedef double Vector3[3];
83 
84 // inverse(original_matrix, inverse_matrix)
85 //
86 // calculate the inverse of a 4x4 matrix
87 //
88 // -1
89 // A  = ___1__ adjoint A
90 //       det A
91 
92 //  double = determinant2x2(double a, double b, double c, double d)
93 //
94 //  calculate the determinant of a 2x2 matrix.
95 
Determinant2x2(double a,double b,double c,double d)96 static double Determinant2x2(double a, double b, double c, double d) {
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 
Determinant3x3(double a1,double a2,double a3,double b1,double b2,double b3,double c1,double c2,double c3)109 static double Determinant3x3(double a1,
110                              double a2,
111                              double a3,
112                              double b1,
113                              double b2,
114                              double b3,
115                              double c1,
116                              double c2,
117                              double c3) {
118   return a1 * Determinant2x2(b2, b3, c2, c3) -
119          b1 * Determinant2x2(a2, a3, c2, c3) +
120          c1 * Determinant2x2(a2, a3, b2, b3);
121 }
122 
123 //  double = determinant4x4(matrix)
124 //
125 //  calculate the determinant of a 4x4 matrix.
126 
Determinant4x4(const TransformationMatrix::Matrix4 & m)127 static double Determinant4x4(const TransformationMatrix::Matrix4& m) {
128   // Assign to individual variable names to aid selecting
129   // correct elements
130 
131   double a1 = m[0][0];
132   double b1 = m[0][1];
133   double c1 = m[0][2];
134   double d1 = m[0][3];
135 
136   double a2 = m[1][0];
137   double b2 = m[1][1];
138   double c2 = m[1][2];
139   double d2 = m[1][3];
140 
141   double a3 = m[2][0];
142   double b3 = m[2][1];
143   double c3 = m[2][2];
144   double d3 = m[2][3];
145 
146   double a4 = m[3][0];
147   double b4 = m[3][1];
148   double c4 = m[3][2];
149   double d4 = m[3][3];
150 
151   return a1 * Determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
152          b1 * Determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
153          c1 * Determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
154          d1 * Determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
155 }
156 
157 #if !defined(ARCH_CPU_ARM64) && !HAVE_MIPS_MSA_INTRINSICS
158 // adjoint( original_matrix, inverse_matrix )
159 //
160 //   calculate the adjoint of a 4x4 matrix
161 //
162 //    Let  a   denote the minor determinant of matrix A obtained by
163 //         ij
164 //
165 //    deleting the ith row and jth column from A.
166 //
167 //                  i+j
168 //   Let  b   = (-1)    a
169 //        ij            ji
170 //
171 //  The matrix B = (b  ) is the adjoint of A
172 //                   ij
173 
Adjoint(const TransformationMatrix::Matrix4 & matrix,TransformationMatrix::Matrix4 & result)174 static inline void Adjoint(const TransformationMatrix::Matrix4& matrix,
175                            TransformationMatrix::Matrix4& result) {
176   // Assign to individual variable names to aid
177   // selecting correct values
178   double a1 = matrix[0][0];
179   double b1 = matrix[0][1];
180   double c1 = matrix[0][2];
181   double d1 = matrix[0][3];
182 
183   double a2 = matrix[1][0];
184   double b2 = matrix[1][1];
185   double c2 = matrix[1][2];
186   double d2 = matrix[1][3];
187 
188   double a3 = matrix[2][0];
189   double b3 = matrix[2][1];
190   double c3 = matrix[2][2];
191   double d3 = matrix[2][3];
192 
193   double a4 = matrix[3][0];
194   double b4 = matrix[3][1];
195   double c4 = matrix[3][2];
196   double d4 = matrix[3][3];
197 
198   // Row column labeling reversed since we transpose rows & columns
199   result[0][0] = Determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
200   result[1][0] = -Determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
201   result[2][0] = Determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
202   result[3][0] = -Determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
203 
204   result[0][1] = -Determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
205   result[1][1] = Determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
206   result[2][1] = -Determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
207   result[3][1] = Determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
208 
209   result[0][2] = Determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
210   result[1][2] = -Determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
211   result[2][2] = Determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
212   result[3][2] = -Determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
213 
214   result[0][3] = -Determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
215   result[1][3] = Determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
216   result[2][3] = -Determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
217   result[3][3] = Determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
218 }
219 #endif
220 
221 // Returns false if the matrix is not invertible
Inverse(const TransformationMatrix::Matrix4 & matrix,TransformationMatrix::Matrix4 & result)222 static bool Inverse(const TransformationMatrix::Matrix4& matrix,
223                     TransformationMatrix::Matrix4& result) {
224   // Calculate the 4x4 determinant
225   // If the determinant is zero,
226   // then the inverse matrix is not unique.
227   double det = Determinant4x4(matrix);
228 
229   if (det == 0)
230     return false;
231 
232 #if defined(ARCH_CPU_ARM64)
233   double rdet = 1 / det;
234   const double* mat = &(matrix[0][0]);
235   double* pr = &(result[0][0]);
236   asm volatile(
237       // mat: v16 - v23
238       // m11, m12, m13, m14
239       // m21, m22, m23, m24
240       // m31, m32, m33, m34
241       // m41, m42, m43, m44
242       "ld1 {v16.2d - v19.2d}, [%[mat]], 64  \n\t"
243       "ld1 {v20.2d - v23.2d}, [%[mat]]      \n\t"
244       "ins v30.d[0], %[rdet]         \n\t"
245       // Determinant: right mat2x2
246       "trn1 v0.2d, v17.2d, v21.2d    \n\t"
247       "trn2 v1.2d, v19.2d, v23.2d    \n\t"
248       "trn2 v2.2d, v17.2d, v21.2d    \n\t"
249       "trn1 v3.2d, v19.2d, v23.2d    \n\t"
250       "trn2 v5.2d, v21.2d, v23.2d    \n\t"
251       "trn1 v4.2d, v17.2d, v19.2d    \n\t"
252       "trn2 v6.2d, v17.2d, v19.2d    \n\t"
253       "trn1 v7.2d, v21.2d, v23.2d    \n\t"
254       "trn2 v25.2d, v23.2d, v21.2d   \n\t"
255       "trn1 v27.2d, v23.2d, v21.2d   \n\t"
256       "fmul v0.2d, v0.2d, v1.2d      \n\t"
257       "fmul v1.2d, v4.2d, v5.2d      \n\t"
258       "fmls v0.2d, v2.2d, v3.2d      \n\t"
259       "fmul v2.2d, v4.2d, v25.2d     \n\t"
260       "fmls v1.2d, v6.2d, v7.2d      \n\t"
261       "fmls v2.2d, v6.2d, v27.2d     \n\t"
262       // Adjoint:
263       // v24: A11A12, v25: A13A14
264       // v26: A21A22, v27: A23A24
265       "fmul v3.2d, v18.2d, v0.d[1]   \n\t"
266       "fmul v4.2d, v16.2d, v0.d[1]   \n\t"
267       "fmul v5.2d, v16.2d, v1.d[1]   \n\t"
268       "fmul v6.2d, v16.2d, v2.d[1]   \n\t"
269       "fmls v3.2d, v20.2d, v1.d[1]   \n\t"
270       "fmls v4.2d, v20.2d, v2.d[0]   \n\t"
271       "fmls v5.2d, v18.2d, v2.d[0]   \n\t"
272       "fmls v6.2d, v18.2d, v1.d[0]   \n\t"
273       "fmla v3.2d, v22.2d, v2.d[1]   \n\t"
274       "fmla v4.2d, v22.2d, v1.d[0]   \n\t"
275       "fmla v5.2d, v22.2d, v0.d[0]   \n\t"
276       "fmla v6.2d, v20.2d, v0.d[0]   \n\t"
277       "fneg v3.2d, v3.2d             \n\t"
278       "fneg v5.2d, v5.2d             \n\t"
279       "trn1 v26.2d, v3.2d, v4.2d     \n\t"
280       "trn1 v27.2d, v5.2d, v6.2d     \n\t"
281       "trn2 v24.2d, v3.2d, v4.2d     \n\t"
282       "trn2 v25.2d, v5.2d, v6.2d     \n\t"
283       "fneg v24.2d, v24.2d           \n\t"
284       "fneg v25.2d, v25.2d           \n\t"
285       // Inverse
286       // v24: I11I12, v25: I13I14
287       // v26: I21I22, v27: I23I24
288       "fmul v24.2d, v24.2d, v30.d[0] \n\t"
289       "fmul v25.2d, v25.2d, v30.d[0] \n\t"
290       "fmul v26.2d, v26.2d, v30.d[0] \n\t"
291       "fmul v27.2d, v27.2d, v30.d[0] \n\t"
292       "st1 {v24.2d - v27.2d}, [%[pr]], 64 \n\t"
293       // Determinant: left mat2x2
294       "trn1 v0.2d, v16.2d, v20.2d    \n\t"
295       "trn2 v1.2d, v18.2d, v22.2d    \n\t"
296       "trn2 v2.2d, v16.2d, v20.2d    \n\t"
297       "trn1 v3.2d, v18.2d, v22.2d    \n\t"
298       "trn2 v5.2d, v20.2d, v22.2d    \n\t"
299       "trn1 v4.2d, v16.2d, v18.2d    \n\t"
300       "trn2 v6.2d, v16.2d, v18.2d    \n\t"
301       "trn1 v7.2d, v20.2d, v22.2d    \n\t"
302       "trn2 v25.2d, v22.2d, v20.2d   \n\t"
303       "trn1 v27.2d, v22.2d, v20.2d   \n\t"
304       "fmul v0.2d, v0.2d, v1.2d      \n\t"
305       "fmul v1.2d, v4.2d, v5.2d      \n\t"
306       "fmls v0.2d, v2.2d, v3.2d      \n\t"
307       "fmul v2.2d, v4.2d, v25.2d     \n\t"
308       "fmls v1.2d, v6.2d, v7.2d      \n\t"
309       "fmls v2.2d, v6.2d, v27.2d     \n\t"
310       // Adjoint:
311       // v24: A31A32, v25: A33A34
312       // v26: A41A42, v27: A43A44
313       "fmul v3.2d, v19.2d, v0.d[1]   \n\t"
314       "fmul v4.2d, v17.2d, v0.d[1]   \n\t"
315       "fmul v5.2d, v17.2d, v1.d[1]   \n\t"
316       "fmul v6.2d, v17.2d, v2.d[1]   \n\t"
317       "fmls v3.2d, v21.2d, v1.d[1]   \n\t"
318       "fmls v4.2d, v21.2d, v2.d[0]   \n\t"
319       "fmls v5.2d, v19.2d, v2.d[0]   \n\t"
320       "fmls v6.2d, v19.2d, v1.d[0]   \n\t"
321       "fmla v3.2d, v23.2d, v2.d[1]   \n\t"
322       "fmla v4.2d, v23.2d, v1.d[0]   \n\t"
323       "fmla v5.2d, v23.2d, v0.d[0]   \n\t"
324       "fmla v6.2d, v21.2d, v0.d[0]   \n\t"
325       "fneg v3.2d, v3.2d             \n\t"
326       "fneg v5.2d, v5.2d             \n\t"
327       "trn1 v26.2d, v3.2d, v4.2d     \n\t"
328       "trn1 v27.2d, v5.2d, v6.2d     \n\t"
329       "trn2 v24.2d, v3.2d, v4.2d     \n\t"
330       "trn2 v25.2d, v5.2d, v6.2d     \n\t"
331       "fneg v24.2d, v24.2d           \n\t"
332       "fneg v25.2d, v25.2d           \n\t"
333       // Inverse
334       // v24: I31I32, v25: I33I34
335       // v26: I41I42, v27: I43I44
336       "fmul v24.2d, v24.2d, v30.d[0] \n\t"
337       "fmul v25.2d, v25.2d, v30.d[0] \n\t"
338       "fmul v26.2d, v26.2d, v30.d[0] \n\t"
339       "fmul v27.2d, v27.2d, v30.d[0] \n\t"
340       "st1 {v24.2d - v27.2d}, [%[pr]] \n\t"
341       : [mat] "+r"(mat), [pr] "+r"(pr)
342       : [rdet] "r"(rdet)
343       : "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16", "v17",
344         "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27",
345         "v28", "v29", "v30");
346 #elif defined(HAVE_MIPS_MSA_INTRINSICS)
347   const double rDet = 1 / det;
348   const double* mat = &(matrix[0][0]);
349   v2f64 mat0, mat1, mat2, mat3, mat4, mat5, mat6, mat7;
350   v2f64 rev2, rev3, rev4, rev5, rev6, rev7;
351   v2f64 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
352   v2f64 det0, det1, det2, tmp8, tmp9, tmp10, tmp11;
353   const v2f64 rdet = COPY_DOUBLE_TO_VECTOR(rDet);
354   // mat0 mat1 --> m00 m01 m02 m03
355   // mat2 mat3 --> m10 m11 m12 m13
356   // mat4 mat5 --> m20 m21 m22 m23
357   // mat6 mat7 --> m30 m31 m32 m33
358   LD_DP8(mat, 2, mat0, mat1, mat2, mat3, mat4, mat5, mat6, mat7);
359 
360   // Right half
361   rev3 = SLDI_D(mat3, mat3, 8);  // m13 m12
362   rev5 = SLDI_D(mat5, mat5, 8);  // m23 m22
363   rev7 = SLDI_D(mat7, mat7, 8);  // m33 m32
364 
365   // 2*2 Determinants
366   // for A00 & A01
367   tmp0 = mat5 * rev7;
368   tmp1 = mat3 * rev7;
369   tmp2 = mat3 * rev5;
370   // for A10 & A11
371   tmp3 = mat1 * rev7;
372   tmp4 = mat1 * rev5;
373   // for A20 & A21
374   tmp5 = mat1 * rev3;
375   // for A30 & A31
376   tmp6 = (v2f64)__msa_ilvr_d((v2i64)tmp1, (v2i64)tmp0);
377   tmp7 = (v2f64)__msa_ilvl_d((v2i64)tmp1, (v2i64)tmp0);
378   det0 = tmp6 - tmp7;
379   tmp6 = (v2f64)__msa_ilvr_d((v2i64)tmp3, (v2i64)tmp2);
380   tmp7 = (v2f64)__msa_ilvl_d((v2i64)tmp3, (v2i64)tmp2);
381   det1 = tmp6 - tmp7;
382   tmp6 = (v2f64)__msa_ilvr_d((v2i64)tmp5, (v2i64)tmp4);
383   tmp7 = (v2f64)__msa_ilvl_d((v2i64)tmp5, (v2i64)tmp4);
384   det2 = tmp6 - tmp7;
385 
386   // Co-factors
387   tmp0 = mat0 * (v2f64)__msa_splati_d((v2i64)det0, 0);
388   tmp1 = mat0 * (v2f64)__msa_splati_d((v2i64)det0, 1);
389   tmp2 = mat0 * (v2f64)__msa_splati_d((v2i64)det1, 0);
390   tmp3 = mat2 * (v2f64)__msa_splati_d((v2i64)det0, 0);
391   tmp4 = mat2 * (v2f64)__msa_splati_d((v2i64)det1, 1);
392   tmp5 = mat2 * (v2f64)__msa_splati_d((v2i64)det2, 0);
393   tmp6 = mat4 * (v2f64)__msa_splati_d((v2i64)det0, 1);
394   tmp7 = mat4 * (v2f64)__msa_splati_d((v2i64)det1, 1);
395   tmp8 = mat4 * (v2f64)__msa_splati_d((v2i64)det2, 1);
396   tmp9 = mat6 * (v2f64)__msa_splati_d((v2i64)det1, 0);
397   tmp10 = mat6 * (v2f64)__msa_splati_d((v2i64)det2, 0);
398   tmp11 = mat6 * (v2f64)__msa_splati_d((v2i64)det2, 1);
399 
400   tmp0 -= tmp7;
401   tmp1 -= tmp4;
402   tmp2 -= tmp5;
403   tmp3 -= tmp6;
404   tmp0 += tmp10;
405   tmp1 += tmp11;
406   tmp2 += tmp8;
407   tmp3 += tmp9;
408 
409   // Multiply with 1/det
410   tmp0 *= rdet;
411   tmp1 *= rdet;
412   tmp2 *= rdet;
413   tmp3 *= rdet;
414 
415   // Inverse: Upper half
416   result[0][0] = tmp3[1];
417   result[0][1] = -tmp0[1];
418   result[0][2] = tmp1[1];
419   result[0][3] = -tmp2[1];
420   result[1][0] = -tmp3[0];
421   result[1][1] = tmp0[0];
422   result[1][2] = -tmp1[0];
423   result[1][3] = tmp2[0];
424   // Left half
425   rev2 = SLDI_D(mat2, mat2, 8);  // m13 m12
426   rev4 = SLDI_D(mat4, mat4, 8);  // m23 m22
427   rev6 = SLDI_D(mat6, mat6, 8);  // m33 m32
428 
429   // 2*2 Determinants
430   // for A00 & A01
431   tmp0 = mat4 * rev6;
432   tmp1 = mat2 * rev6;
433   tmp2 = mat2 * rev4;
434   // for A10 & A11
435   tmp3 = mat0 * rev6;
436   tmp4 = mat0 * rev4;
437   // for A20 & A21
438   tmp5 = mat0 * rev2;
439   // for A30 & A31
440   tmp6 = (v2f64)__msa_ilvr_d((v2i64)tmp1, (v2i64)tmp0);
441   tmp7 = (v2f64)__msa_ilvl_d((v2i64)tmp1, (v2i64)tmp0);
442   det0 = tmp6 - tmp7;
443   tmp6 = (v2f64)__msa_ilvr_d((v2i64)tmp3, (v2i64)tmp2);
444   tmp7 = (v2f64)__msa_ilvl_d((v2i64)tmp3, (v2i64)tmp2);
445   det1 = tmp6 - tmp7;
446   tmp6 = (v2f64)__msa_ilvr_d((v2i64)tmp5, (v2i64)tmp4);
447   tmp7 = (v2f64)__msa_ilvl_d((v2i64)tmp5, (v2i64)tmp4);
448   det2 = tmp6 - tmp7;
449 
450   // Co-factors
451   tmp0 = mat3 * (v2f64)__msa_splati_d((v2i64)det0, 0);
452   tmp1 = mat1 * (v2f64)__msa_splati_d((v2i64)det0, 1);
453   tmp2 = mat1 * (v2f64)__msa_splati_d((v2i64)det0, 0);
454   tmp3 = mat1 * (v2f64)__msa_splati_d((v2i64)det1, 0);
455   tmp4 = mat3 * (v2f64)__msa_splati_d((v2i64)det1, 1);
456   tmp5 = mat3 * (v2f64)__msa_splati_d((v2i64)det2, 0);
457   tmp6 = mat5 * (v2f64)__msa_splati_d((v2i64)det0, 1);
458   tmp7 = mat5 * (v2f64)__msa_splati_d((v2i64)det1, 1);
459   tmp8 = mat5 * (v2f64)__msa_splati_d((v2i64)det2, 1);
460   tmp9 = mat7 * (v2f64)__msa_splati_d((v2i64)det1, 0);
461   tmp10 = mat7 * (v2f64)__msa_splati_d((v2i64)det2, 0);
462   tmp11 = mat7 * (v2f64)__msa_splati_d((v2i64)det2, 1);
463   tmp0 -= tmp6;
464   tmp1 -= tmp4;
465   tmp2 -= tmp7;
466   tmp3 -= tmp5;
467   tmp0 += tmp9;
468   tmp1 += tmp11;
469   tmp2 += tmp10;
470   tmp3 += tmp8;
471 
472   // Multiply with 1/det
473   tmp0 *= rdet;
474   tmp1 *= rdet;
475   tmp2 *= rdet;
476   tmp3 *= rdet;
477 
478   // Inverse: Lower half
479   result[2][0] = tmp0[1];
480   result[2][1] = -tmp2[1];
481   result[2][2] = tmp1[1];
482   result[2][3] = -tmp3[1];
483   result[3][0] = -tmp0[0];
484   result[3][1] = tmp2[0];
485   result[3][2] = -tmp1[0];
486   result[3][3] = tmp3[0];
487 #else
488   // Calculate the adjoint matrix
489   Adjoint(matrix, result);
490 
491   double rdet = 1 / det;
492 
493   // Scale the adjoint matrix to get the inverse
494   for (int i = 0; i < 4; i++)
495     for (int j = 0; j < 4; j++)
496       result[i][j] = result[i][j] * rdet;
497 #endif
498   return true;
499 }
500 
501 // End of code adapted from Matrix Inversion by Richard Carling
502 
503 // Perform a decomposition on the passed matrix, return false if unsuccessful
504 // From Graphics Gems: unmatrix.c
505 
506 // Transpose rotation portion of matrix a, return b
TransposeMatrix4(const TransformationMatrix::Matrix4 & a,TransformationMatrix::Matrix4 & b)507 static void TransposeMatrix4(const TransformationMatrix::Matrix4& a,
508                              TransformationMatrix::Matrix4& b) {
509   for (int i = 0; i < 4; i++)
510     for (int j = 0; j < 4; j++)
511       b[i][j] = a[j][i];
512 }
513 
514 // Multiply a homogeneous point by a matrix and return the transformed point
V4MulPointByMatrix(const Vector4 p,const TransformationMatrix::Matrix4 & m,Vector4 result)515 static void V4MulPointByMatrix(const Vector4 p,
516                                const TransformationMatrix::Matrix4& m,
517                                Vector4 result) {
518   result[0] =
519       (p[0] * m[0][0]) + (p[1] * m[1][0]) + (p[2] * m[2][0]) + (p[3] * m[3][0]);
520   result[1] =
521       (p[0] * m[0][1]) + (p[1] * m[1][1]) + (p[2] * m[2][1]) + (p[3] * m[3][1]);
522   result[2] =
523       (p[0] * m[0][2]) + (p[1] * m[1][2]) + (p[2] * m[2][2]) + (p[3] * m[3][2]);
524   result[3] =
525       (p[0] * m[0][3]) + (p[1] * m[1][3]) + (p[2] * m[2][3]) + (p[3] * m[3][3]);
526 }
527 
V3Length(Vector3 a)528 static double V3Length(Vector3 a) {
529   return std::sqrt((a[0] * a[0]) + (a[1] * a[1]) + (a[2] * a[2]));
530 }
531 
V3Scale(Vector3 v,double desired_length)532 static void V3Scale(Vector3 v, double desired_length) {
533   double len = V3Length(v);
534   if (len != 0) {
535     double l = desired_length / len;
536     v[0] *= l;
537     v[1] *= l;
538     v[2] *= l;
539   }
540 }
541 
V3Dot(const Vector3 a,const Vector3 b)542 static double V3Dot(const Vector3 a, const Vector3 b) {
543   return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
544 }
545 
546 // Make a linear combination of two vectors and return the result.
547 // result = (a * ascl) + (b * bscl)
V3Combine(const Vector3 a,const Vector3 b,Vector3 result,double ascl,double bscl)548 static void V3Combine(const Vector3 a,
549                       const Vector3 b,
550                       Vector3 result,
551                       double ascl,
552                       double bscl) {
553   result[0] = (ascl * a[0]) + (bscl * b[0]);
554   result[1] = (ascl * a[1]) + (bscl * b[1]);
555   result[2] = (ascl * a[2]) + (bscl * b[2]);
556 }
557 
558 // Return the cross product result = a cross b */
V3Cross(const Vector3 a,const Vector3 b,Vector3 result)559 static void V3Cross(const Vector3 a, const Vector3 b, Vector3 result) {
560   result[0] = (a[1] * b[2]) - (a[2] * b[1]);
561   result[1] = (a[2] * b[0]) - (a[0] * b[2]);
562   result[2] = (a[0] * b[1]) - (a[1] * b[0]);
563 }
564 
565 // TODO(crbug/937296): This implementation is virtually identical to the
566 // implementation in ui/gfx/transform_util with the main difference being
567 // the representation of the underlying matrix. These implementations should be
568 // consolidated.
Decompose(const TransformationMatrix::Matrix4 & mat,TransformationMatrix::DecomposedType & result)569 static bool Decompose(const TransformationMatrix::Matrix4& mat,
570                       TransformationMatrix::DecomposedType& result) {
571   // https://www.w3.org/TR/css-transforms-2/#decomposing-a-3d-matrix.
572 
573   TransformationMatrix::Matrix4 local_matrix;
574   memcpy(&local_matrix, &mat, sizeof(TransformationMatrix::Matrix4));
575 
576   // Normalize the matrix.
577   if (local_matrix[3][3] == 0)
578     return false;
579 
580   int i, j;
581   for (i = 0; i < 4; i++)
582     for (j = 0; j < 4; j++)
583       local_matrix[i][j] /= local_matrix[3][3];
584 
585   // perspectiveMatrix is used to solve for perspective, but it also provides
586   // an easy way to test for singularity of the upper 3x3 component.
587   TransformationMatrix::Matrix4 perspective_matrix;
588   memcpy(&perspective_matrix, &local_matrix,
589          sizeof(TransformationMatrix::Matrix4));
590   for (i = 0; i < 3; i++)
591     perspective_matrix[i][3] = 0;
592   perspective_matrix[3][3] = 1;
593 
594   if (Determinant4x4(perspective_matrix) == 0)
595     return false;
596 
597   // First, isolate perspective.  This is the messiest.
598   if (local_matrix[0][3] != 0 || local_matrix[1][3] != 0 ||
599       local_matrix[2][3] != 0) {
600     // rightHandSide is the right hand side of the equation.
601     Vector4 right_hand_side;
602     right_hand_side[0] = local_matrix[0][3];
603     right_hand_side[1] = local_matrix[1][3];
604     right_hand_side[2] = local_matrix[2][3];
605     right_hand_side[3] = local_matrix[3][3];
606 
607     // Solve the equation by inverting perspectiveMatrix and multiplying
608     // rightHandSide by the inverse.  (This is the easiest way, not
609     // necessarily the best.)
610     TransformationMatrix::Matrix4 inverse_perspective_matrix,
611         transposed_inverse_perspective_matrix;
612     if (!Inverse(perspective_matrix, inverse_perspective_matrix))
613       return false;
614     TransposeMatrix4(inverse_perspective_matrix,
615                      transposed_inverse_perspective_matrix);
616 
617     Vector4 perspective_point;
618     V4MulPointByMatrix(right_hand_side, transposed_inverse_perspective_matrix,
619                        perspective_point);
620 
621     result.perspective_x = perspective_point[0];
622     result.perspective_y = perspective_point[1];
623     result.perspective_z = perspective_point[2];
624     result.perspective_w = perspective_point[3];
625 
626     // Clear the perspective partition
627     local_matrix[0][3] = local_matrix[1][3] = local_matrix[2][3] = 0;
628     local_matrix[3][3] = 1;
629   } else {
630     // No perspective.
631     result.perspective_x = result.perspective_y = result.perspective_z = 0;
632     result.perspective_w = 1;
633   }
634 
635   // Next take care of translation (easy).
636   result.translate_x = local_matrix[3][0];
637   local_matrix[3][0] = 0;
638   result.translate_y = local_matrix[3][1];
639   local_matrix[3][1] = 0;
640   result.translate_z = local_matrix[3][2];
641   local_matrix[3][2] = 0;
642 
643   // Vector4 type and functions need to be added to the common set.
644   // Note: Deviating from the spec in terms of variable naming. The matrix is
645   // stored on column major order and not row major. Using the variable 'row'
646   // instead of 'column' in the spec pseudocode has been the source of
647   // confusion, specifically in sorting out rotations.
648   Vector3 column[3], pdum3;
649 
650   // Now get scale and shear.
651   for (i = 0; i < 3; i++) {
652     column[i][0] = local_matrix[i][0];
653     column[i][1] = local_matrix[i][1];
654     column[i][2] = local_matrix[i][2];
655   }
656 
657   // Compute X scale factor and normalize the first column.
658   result.scale_x = V3Length(column[0]);
659   V3Scale(column[0], 1.0);
660 
661   // Compute XY shear factor and make 2nd row orthogonal to 1st.
662   result.skew_xy = V3Dot(column[0], column[1]);
663   V3Combine(column[1], column[0], column[1], 1.0, -result.skew_xy);
664 
665   // Now, compute Y scale and normalize 2nd column.
666   result.scale_y = V3Length(column[1]);
667   V3Scale(column[1], 1.0);
668   result.skew_xy /= result.scale_y;
669 
670   // Compute XZ and YZ shears, and orthogonalize the 3rd column.
671   result.skew_xz = V3Dot(column[0], column[2]);
672   V3Combine(column[2], column[0], column[2], 1.0, -result.skew_xz);
673   result.skew_yz = V3Dot(column[1], column[2]);
674   V3Combine(column[2], column[1], column[2], 1.0, -result.skew_yz);
675 
676   // Next, get Z scale and normalize the 3rd column.
677   result.scale_z = V3Length(column[2]);
678   V3Scale(column[2], 1.0);
679   result.skew_xz /= result.scale_z;
680   result.skew_yz /= result.scale_z;
681 
682   // At this point, the matrix (in column[]) is orthonormal.
683   // Check for a coordinate system flip.  If the determinant
684   // is -1, then negate the matrix and the scaling factors.
685   V3Cross(column[1], column[2], pdum3);
686   if (V3Dot(column[0], pdum3) < 0) {
687     // Note that flipping only one of the 3 scaling factors would also flip
688     // the sign of the determinant. By flipping all 3, we turn a 2D matrix
689     // interpolation into a 3D interpolation.
690     result.scale_x *= -1;
691     result.scale_y *= -1;
692     result.scale_z *= -1;
693 
694     for (i = 0; i < 3; i++) {
695       column[i][0] *= -1;
696       column[i][1] *= -1;
697       column[i][2] *= -1;
698     }
699   }
700 
701   // Lastly, compute the quaternions.
702   // See https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion.
703   // Note: deviating from spec (http://www.w3.org/TR/css3-transforms/)
704   // which has a degenerate case when the trace (t) of the orthonormal matrix
705   // (Q) approaches -1. In the Wikipedia article, Q_ij is indexing on row then
706   // column. Thus, Q_ij = column[j][i].
707 
708   // The following are equivalent represnetations of the rotation matrix:
709   //
710   // Axis-angle form:
711   //
712   //      [ c+(1-c)x^2  (1-c)xy-sz  (1-c)xz+sy ]    c = cos theta
713   // R =  [ (1-c)xy+sz  c+(1-c)y^2  (1-c)yz-sx ]    s = sin theta
714   //      [ (1-c)xz-sy  (1-c)yz+sx  c+(1-c)z^2 ]    [x,y,z] = axis or rotation
715   //
716   // The sum of the diagonal elements (trace) is a simple function of the cosine
717   // of the angle. The w component of the quaternion is cos(theta/2), and we
718   // make use of the double angle formula to directly compute w from the
719   // trace. Differences between pairs of skew symmetric elements in this matrix
720   // isolate the remaining components. Since w can be zero (also numerically
721   // unstable if near zero), we cannot rely solely on this approach to compute
722   // the quaternion components.
723   //
724   // Quaternion form:
725   //
726   //       [ 1-2(y^2+z^2)    2(xy-zw)      2(xz+yw)   ]
727   //  r =  [   2(xy+zw)    1-2(x^2+z^2)    2(yz-xw)   ]    q = (x,y,y,w)
728   //       [   2(xz-yw)      2(yz+xw)    1-2(x^2+y^2) ]
729   //
730   // Different linear combinations of the diagonal elements isolates x, y or z.
731   // Sums or differences between skew symmetric elements isolate the remainder.
732 
733   double r, s, t, x, y, z, w;
734 
735   t = column[0][0] + column[1][1] + column[2][2];  // trace of Q
736 
737   // https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion
738   if (1 + t > 0.001) {
739     // Numerically stable as long as 1+t is not close to zero. Otherwise use the
740     // diagonal element with the greatest value to compute the quaternions.
741     r = std::sqrt(1.0 + t);
742     s = 0.5 / r;
743     w = 0.5 * r;
744     x = (column[1][2] - column[2][1]) * s;
745     y = (column[2][0] - column[0][2]) * s;
746     z = (column[0][1] - column[1][0]) * s;
747   } else if (column[0][0] > column[1][1] && column[0][0] > column[2][2]) {
748     // Q_xx is largest.
749     r = std::sqrt(1.0 + column[0][0] - column[1][1] - column[2][2]);
750     s = 0.5 / r;
751     x = 0.5 * r;
752     y = (column[1][0] - column[0][1]) * s;
753     z = (column[2][0] + column[0][2]) * s;
754     w = (column[1][2] - column[2][1]) * s;
755   } else if (column[1][1] > column[2][2]) {
756     // Q_yy is largest.
757     r = std::sqrt(1.0 - column[0][0] + column[1][1] - column[2][2]);
758     s = 0.5 / r;
759     x = (column[1][0] + column[0][1]) * s;
760     y = 0.5 * r;
761     z = (column[2][1] + column[1][2]) * s;
762     w = (column[2][0] - column[0][2]) * s;
763   } else {
764     // Q_zz is largest.
765     r = std::sqrt(1.0 - column[0][0] - column[1][1] + column[2][2]);
766     s = 0.5 / r;
767     x = (column[2][0] + column[0][2]) * s;
768     y = (column[2][1] + column[1][2]) * s;
769     z = 0.5 * r;
770     w = (column[0][1] - column[1][0]) * s;
771   }
772 
773   result.quaternion_x = x;
774   result.quaternion_y = y;
775   result.quaternion_z = z;
776   result.quaternion_w = w;
777 
778   return true;
779 }
780 
ToQuaterion(const TransformationMatrix::DecomposedType & decomp)781 Quaternion ToQuaterion(const TransformationMatrix::DecomposedType& decomp) {
782   return Quaternion(decomp.quaternion_x, decomp.quaternion_y,
783                     decomp.quaternion_z, decomp.quaternion_w);
784 }
785 
Slerp(TransformationMatrix::DecomposedType & from_decomp,const TransformationMatrix::DecomposedType & to_decomp,double progress)786 void Slerp(TransformationMatrix::DecomposedType& from_decomp,
787            const TransformationMatrix::DecomposedType& to_decomp,
788            double progress) {
789   Quaternion qa = ToQuaterion(from_decomp);
790   Quaternion qb = ToQuaterion(to_decomp);
791   Quaternion qc = qa.Slerp(qb, progress);
792   from_decomp.quaternion_x = qc.x();
793   from_decomp.quaternion_y = qc.y();
794   from_decomp.quaternion_z = qc.z();
795   from_decomp.quaternion_w = qc.w();
796 }
797 
798 // End of Supporting Math Functions
799 
TransformationMatrix(const AffineTransform & t)800 TransformationMatrix::TransformationMatrix(const AffineTransform& t) {
801   SetMatrix(t.A(), t.B(), t.C(), t.D(), t.E(), t.F());
802 }
803 
Scale(double s)804 TransformationMatrix& TransformationMatrix::Scale(double s) {
805   return ScaleNonUniform(s, s);
806 }
807 
ProjectPoint(const FloatPoint & p,bool * clamped) const808 FloatPoint TransformationMatrix::ProjectPoint(const FloatPoint& p,
809                                               bool* clamped) const {
810   // This is basically raytracing. We have a point in the destination
811   // plane with z=0, and we cast a ray parallel to the z-axis from that
812   // point to find the z-position at which it intersects the z=0 plane
813   // with the transform applied. Once we have that point we apply the
814   // inverse transform to find the corresponding point in the source
815   // space.
816   //
817   // Given a plane with normal Pn, and a ray starting at point R0 and
818   // with direction defined by the vector Rd, we can find the
819   // intersection point as a distance d from R0 in units of Rd by:
820   //
821   // d = -dot (Pn', R0) / dot (Pn', Rd)
822   if (clamped)
823     *clamped = false;
824 
825   if (M33() == 0) {
826     // In this case, the projection plane is parallel to the ray we are trying
827     // to trace, and there is no well-defined value for the projection.
828     return FloatPoint();
829   }
830 
831   double x = p.X();
832   double y = p.Y();
833   double z = -(M13() * x + M23() * y + M43()) / M33();
834 
835   // FIXME: use multVecMatrix()
836   double out_x = x * M11() + y * M21() + z * M31() + M41();
837   double out_y = x * M12() + y * M22() + z * M32() + M42();
838 
839   double w = x * M14() + y * M24() + z * M34() + M44();
840   if (w <= 0) {
841     // Using int max causes overflow when other code uses the projected point.
842     // To represent infinity yet reduce the risk of overflow, we use a large but
843     // not-too-large number here when clamping.
844     const int kLargeNumber = 100000000 / kFixedPointDenominator;
845     out_x = copysign(kLargeNumber, out_x);
846     out_y = copysign(kLargeNumber, out_y);
847     if (clamped)
848       *clamped = true;
849   } else if (w != 1) {
850     out_x /= w;
851     out_y /= w;
852   }
853 
854   return FloatPoint(static_cast<float>(out_x), static_cast<float>(out_y));
855 }
856 
ProjectQuad(const FloatQuad & q) const857 FloatQuad TransformationMatrix::ProjectQuad(const FloatQuad& q) const {
858   FloatQuad projected_quad;
859 
860   bool clamped1 = false;
861   bool clamped2 = false;
862   bool clamped3 = false;
863   bool clamped4 = false;
864 
865   projected_quad.SetP1(ProjectPoint(q.P1(), &clamped1));
866   projected_quad.SetP2(ProjectPoint(q.P2(), &clamped2));
867   projected_quad.SetP3(ProjectPoint(q.P3(), &clamped3));
868   projected_quad.SetP4(ProjectPoint(q.P4(), &clamped4));
869 
870   // If all points on the quad had w < 0, then the entire quad would not be
871   // visible to the projected surface.
872   bool everything_was_clipped = clamped1 && clamped2 && clamped3 && clamped4;
873   if (everything_was_clipped)
874     return FloatQuad();
875 
876   return projected_quad;
877 }
878 
ClampEdgeValue(float f)879 static float ClampEdgeValue(float f) {
880   DCHECK(!std::isnan(f));
881   return clampTo(f, (-LayoutUnit::Max() / 2).ToFloat(),
882                  (LayoutUnit::Max() / 2).ToFloat());
883 }
884 
ClampedBoundsOfProjectedQuad(const FloatQuad & q) const885 LayoutRect TransformationMatrix::ClampedBoundsOfProjectedQuad(
886     const FloatQuad& q) const {
887   FloatRect mapped_quad_bounds = ProjectQuad(q).BoundingBox();
888 
889   float left = ClampEdgeValue(floorf(mapped_quad_bounds.X()));
890   float top = ClampEdgeValue(floorf(mapped_quad_bounds.Y()));
891 
892   float right;
893   if (std::isinf(mapped_quad_bounds.X()) &&
894       std::isinf(mapped_quad_bounds.Width()))
895     right = (LayoutUnit::Max() / 2).ToFloat();
896   else
897     right = ClampEdgeValue(ceilf(mapped_quad_bounds.MaxX()));
898 
899   float bottom;
900   if (std::isinf(mapped_quad_bounds.Y()) &&
901       std::isinf(mapped_quad_bounds.Height()))
902     bottom = (LayoutUnit::Max() / 2).ToFloat();
903   else
904     bottom = ClampEdgeValue(ceilf(mapped_quad_bounds.MaxY()));
905 
906   return LayoutRect(LayoutUnit::Clamp(left), LayoutUnit::Clamp(top),
907                     LayoutUnit::Clamp(right - left),
908                     LayoutUnit::Clamp(bottom - top));
909 }
910 
TransformBox(FloatBox & box) const911 void TransformationMatrix::TransformBox(FloatBox& box) const {
912   FloatBox bounds;
913   bool first_point = true;
914   for (size_t i = 0; i < 2; ++i) {
915     for (size_t j = 0; j < 2; ++j) {
916       for (size_t k = 0; k < 2; ++k) {
917         FloatPoint3D point(box.X(), box.Y(), box.Z());
918         point +=
919             FloatPoint3D(i * box.Width(), j * box.Height(), k * box.Depth());
920         point = MapPoint(point);
921         if (first_point) {
922           bounds.SetOrigin(point);
923           first_point = false;
924         } else {
925           bounds.ExpandTo(point);
926         }
927       }
928     }
929   }
930   box = bounds;
931 }
932 
MapPoint(const FloatPoint & p) const933 FloatPoint TransformationMatrix::MapPoint(const FloatPoint& p) const {
934   if (IsIdentityOrTranslation())
935     return FloatPoint(p.X() + static_cast<float>(matrix_[3][0]),
936                       p.Y() + static_cast<float>(matrix_[3][1]));
937 
938   return InternalMapPoint(p);
939 }
940 
MapPoint(const FloatPoint3D & p) const941 FloatPoint3D TransformationMatrix::MapPoint(const FloatPoint3D& p) const {
942   if (IsIdentityOrTranslation())
943     return FloatPoint3D(p.X() + static_cast<float>(matrix_[3][0]),
944                         p.Y() + static_cast<float>(matrix_[3][1]),
945                         p.Z() + static_cast<float>(matrix_[3][2]));
946 
947   return InternalMapPoint(p);
948 }
949 
MapRect(const IntRect & rect) const950 IntRect TransformationMatrix::MapRect(const IntRect& rect) const {
951   return EnclosingIntRect(MapRect(FloatRect(rect)));
952 }
953 
MapRect(const LayoutRect & r) const954 LayoutRect TransformationMatrix::MapRect(const LayoutRect& r) const {
955   return EnclosingLayoutRect(MapRect(FloatRect(r)));
956 }
957 
MapRect(const FloatRect & r) const958 FloatRect TransformationMatrix::MapRect(const FloatRect& r) const {
959   if (IsIdentityOrTranslation()) {
960     FloatRect mapped_rect(r);
961     mapped_rect.Move(static_cast<float>(matrix_[3][0]),
962                      static_cast<float>(matrix_[3][1]));
963     return mapped_rect;
964   }
965 
966   FloatQuad result;
967 
968   float max_x = r.MaxX();
969   float max_y = r.MaxY();
970   result.SetP1(InternalMapPoint(FloatPoint(r.X(), r.Y())));
971   result.SetP2(InternalMapPoint(FloatPoint(max_x, r.Y())));
972   result.SetP3(InternalMapPoint(FloatPoint(max_x, max_y)));
973   result.SetP4(InternalMapPoint(FloatPoint(r.X(), max_y)));
974 
975   return result.BoundingBox();
976 }
977 
MapQuad(const FloatQuad & q) const978 FloatQuad TransformationMatrix::MapQuad(const FloatQuad& q) const {
979   if (IsIdentityOrTranslation()) {
980     FloatQuad mapped_quad(q);
981     mapped_quad.Move(static_cast<float>(matrix_[3][0]),
982                      static_cast<float>(matrix_[3][1]));
983     return mapped_quad;
984   }
985 
986   FloatQuad result;
987   result.SetP1(InternalMapPoint(q.P1()));
988   result.SetP2(InternalMapPoint(q.P2()));
989   result.SetP3(InternalMapPoint(q.P3()));
990   result.SetP4(InternalMapPoint(q.P4()));
991   return result;
992 }
993 
ScaleNonUniform(double sx,double sy)994 TransformationMatrix& TransformationMatrix::ScaleNonUniform(double sx,
995                                                             double sy) {
996   matrix_[0][0] *= sx;
997   matrix_[0][1] *= sx;
998   matrix_[0][2] *= sx;
999   matrix_[0][3] *= sx;
1000 
1001   matrix_[1][0] *= sy;
1002   matrix_[1][1] *= sy;
1003   matrix_[1][2] *= sy;
1004   matrix_[1][3] *= sy;
1005   return *this;
1006 }
1007 
Scale3d(double sx,double sy,double sz)1008 TransformationMatrix& TransformationMatrix::Scale3d(double sx,
1009                                                     double sy,
1010                                                     double sz) {
1011   ScaleNonUniform(sx, sy);
1012 
1013   matrix_[2][0] *= sz;
1014   matrix_[2][1] *= sz;
1015   matrix_[2][2] *= sz;
1016   matrix_[2][3] *= sz;
1017   return *this;
1018 }
1019 
Rotate3d(const Rotation & rotation)1020 TransformationMatrix& TransformationMatrix::Rotate3d(const Rotation& rotation) {
1021   return Rotate3d(rotation.axis.X(), rotation.axis.Y(), rotation.axis.Z(),
1022                   rotation.angle);
1023 }
1024 
Rotate3d(double x,double y,double z,double angle)1025 TransformationMatrix& TransformationMatrix::Rotate3d(double x,
1026                                                      double y,
1027                                                      double z,
1028                                                      double angle) {
1029   // Normalize the axis of rotation
1030   double length = std::sqrt(x * x + y * y + z * z);
1031   if (length == 0) {
1032     // A direction vector that cannot be normalized, such as [0, 0, 0], will
1033     // cause the rotation to not be applied.
1034     return *this;
1035   } else if (length != 1) {
1036     x /= length;
1037     y /= length;
1038     z /= length;
1039   }
1040 
1041   // Angles are in degrees. Switch to radians.
1042   angle = deg2rad(angle);
1043 
1044   double sin_theta = std::sin(angle);
1045   double cos_theta = std::cos(angle);
1046 
1047   TransformationMatrix mat;
1048 
1049   // Optimize cases where the axis is along a major axis
1050   // Since we've already normalized the vector we don't need to check that the
1051   // other two dimensions are zero
1052   if (x == 1.0) {
1053     mat.matrix_[0][0] = 1.0;
1054     mat.matrix_[0][1] = 0.0;
1055     mat.matrix_[0][2] = 0.0;
1056     mat.matrix_[1][0] = 0.0;
1057     mat.matrix_[1][1] = cos_theta;
1058     mat.matrix_[1][2] = sin_theta;
1059     mat.matrix_[2][0] = 0.0;
1060     mat.matrix_[2][1] = -sin_theta;
1061     mat.matrix_[2][2] = cos_theta;
1062     mat.matrix_[0][3] = mat.matrix_[1][3] = mat.matrix_[2][3] = 0.0;
1063     mat.matrix_[3][0] = mat.matrix_[3][1] = mat.matrix_[3][2] = 0.0;
1064     mat.matrix_[3][3] = 1.0;
1065   } else if (y == 1.0) {
1066     mat.matrix_[0][0] = cos_theta;
1067     mat.matrix_[0][1] = 0.0;
1068     mat.matrix_[0][2] = -sin_theta;
1069     mat.matrix_[1][0] = 0.0;
1070     mat.matrix_[1][1] = 1.0;
1071     mat.matrix_[1][2] = 0.0;
1072     mat.matrix_[2][0] = sin_theta;
1073     mat.matrix_[2][1] = 0.0;
1074     mat.matrix_[2][2] = cos_theta;
1075     mat.matrix_[0][3] = mat.matrix_[1][3] = mat.matrix_[2][3] = 0.0;
1076     mat.matrix_[3][0] = mat.matrix_[3][1] = mat.matrix_[3][2] = 0.0;
1077     mat.matrix_[3][3] = 1.0;
1078   } else if (z == 1.0) {
1079     mat.matrix_[0][0] = cos_theta;
1080     mat.matrix_[0][1] = sin_theta;
1081     mat.matrix_[0][2] = 0.0;
1082     mat.matrix_[1][0] = -sin_theta;
1083     mat.matrix_[1][1] = cos_theta;
1084     mat.matrix_[1][2] = 0.0;
1085     mat.matrix_[2][0] = 0.0;
1086     mat.matrix_[2][1] = 0.0;
1087     mat.matrix_[2][2] = 1.0;
1088     mat.matrix_[0][3] = mat.matrix_[1][3] = mat.matrix_[2][3] = 0.0;
1089     mat.matrix_[3][0] = mat.matrix_[3][1] = mat.matrix_[3][2] = 0.0;
1090     mat.matrix_[3][3] = 1.0;
1091   } else {
1092     // This case is the rotation about an arbitrary unit vector.
1093     //
1094     // Formula is adapted from Wikipedia article on Rotation matrix,
1095     // http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
1096     //
1097     // An alternate resource with the same matrix:
1098     // http://www.fastgraph.com/makegames/3drotation/
1099     //
1100     double one_minus_cos_theta = 1 - cos_theta;
1101     mat.matrix_[0][0] = cos_theta + x * x * one_minus_cos_theta;
1102     mat.matrix_[0][1] = y * x * one_minus_cos_theta + z * sin_theta;
1103     mat.matrix_[0][2] = z * x * one_minus_cos_theta - y * sin_theta;
1104     mat.matrix_[1][0] = x * y * one_minus_cos_theta - z * sin_theta;
1105     mat.matrix_[1][1] = cos_theta + y * y * one_minus_cos_theta;
1106     mat.matrix_[1][2] = z * y * one_minus_cos_theta + x * sin_theta;
1107     mat.matrix_[2][0] = x * z * one_minus_cos_theta + y * sin_theta;
1108     mat.matrix_[2][1] = y * z * one_minus_cos_theta - x * sin_theta;
1109     mat.matrix_[2][2] = cos_theta + z * z * one_minus_cos_theta;
1110     mat.matrix_[0][3] = mat.matrix_[1][3] = mat.matrix_[2][3] = 0.0;
1111     mat.matrix_[3][0] = mat.matrix_[3][1] = mat.matrix_[3][2] = 0.0;
1112     mat.matrix_[3][3] = 1.0;
1113   }
1114   Multiply(mat);
1115   return *this;
1116 }
1117 
Rotate3d(double rx,double ry,double rz)1118 TransformationMatrix& TransformationMatrix::Rotate3d(double rx,
1119                                                      double ry,
1120                                                      double rz) {
1121   // Angles are in degrees. Switch to radians.
1122   rx = deg2rad(rx);
1123   ry = deg2rad(ry);
1124   rz = deg2rad(rz);
1125 
1126   TransformationMatrix mat;
1127 
1128   double sin_theta = std::sin(rz);
1129   double cos_theta = std::cos(rz);
1130 
1131   mat.matrix_[0][0] = cos_theta;
1132   mat.matrix_[0][1] = sin_theta;
1133   mat.matrix_[0][2] = 0.0;
1134   mat.matrix_[1][0] = -sin_theta;
1135   mat.matrix_[1][1] = cos_theta;
1136   mat.matrix_[1][2] = 0.0;
1137   mat.matrix_[2][0] = 0.0;
1138   mat.matrix_[2][1] = 0.0;
1139   mat.matrix_[2][2] = 1.0;
1140   mat.matrix_[0][3] = mat.matrix_[1][3] = mat.matrix_[2][3] = 0.0;
1141   mat.matrix_[3][0] = mat.matrix_[3][1] = mat.matrix_[3][2] = 0.0;
1142   mat.matrix_[3][3] = 1.0;
1143 
1144   TransformationMatrix rmat(mat);
1145 
1146   sin_theta = std::sin(ry);
1147   cos_theta = std::cos(ry);
1148 
1149   mat.matrix_[0][0] = cos_theta;
1150   mat.matrix_[0][1] = 0.0;
1151   mat.matrix_[0][2] = -sin_theta;
1152   mat.matrix_[1][0] = 0.0;
1153   mat.matrix_[1][1] = 1.0;
1154   mat.matrix_[1][2] = 0.0;
1155   mat.matrix_[2][0] = sin_theta;
1156   mat.matrix_[2][1] = 0.0;
1157   mat.matrix_[2][2] = cos_theta;
1158   mat.matrix_[0][3] = mat.matrix_[1][3] = mat.matrix_[2][3] = 0.0;
1159   mat.matrix_[3][0] = mat.matrix_[3][1] = mat.matrix_[3][2] = 0.0;
1160   mat.matrix_[3][3] = 1.0;
1161 
1162   rmat.Multiply(mat);
1163 
1164   sin_theta = std::sin(rx);
1165   cos_theta = std::cos(rx);
1166 
1167   mat.matrix_[0][0] = 1.0;
1168   mat.matrix_[0][1] = 0.0;
1169   mat.matrix_[0][2] = 0.0;
1170   mat.matrix_[1][0] = 0.0;
1171   mat.matrix_[1][1] = cos_theta;
1172   mat.matrix_[1][2] = sin_theta;
1173   mat.matrix_[2][0] = 0.0;
1174   mat.matrix_[2][1] = -sin_theta;
1175   mat.matrix_[2][2] = cos_theta;
1176   mat.matrix_[0][3] = mat.matrix_[1][3] = mat.matrix_[2][3] = 0.0;
1177   mat.matrix_[3][0] = mat.matrix_[3][1] = mat.matrix_[3][2] = 0.0;
1178   mat.matrix_[3][3] = 1.0;
1179 
1180   rmat.Multiply(mat);
1181 
1182   Multiply(rmat);
1183   return *this;
1184 }
1185 
Translate(double tx,double ty)1186 TransformationMatrix& TransformationMatrix::Translate(double tx, double ty) {
1187   matrix_[3][0] += tx * matrix_[0][0] + ty * matrix_[1][0];
1188   matrix_[3][1] += tx * matrix_[0][1] + ty * matrix_[1][1];
1189   matrix_[3][2] += tx * matrix_[0][2] + ty * matrix_[1][2];
1190   matrix_[3][3] += tx * matrix_[0][3] + ty * matrix_[1][3];
1191   return *this;
1192 }
1193 
Translate3d(double tx,double ty,double tz)1194 TransformationMatrix& TransformationMatrix::Translate3d(double tx,
1195                                                         double ty,
1196                                                         double tz) {
1197   matrix_[3][0] += tx * matrix_[0][0] + ty * matrix_[1][0] + tz * matrix_[2][0];
1198   matrix_[3][1] += tx * matrix_[0][1] + ty * matrix_[1][1] + tz * matrix_[2][1];
1199   matrix_[3][2] += tx * matrix_[0][2] + ty * matrix_[1][2] + tz * matrix_[2][2];
1200   matrix_[3][3] += tx * matrix_[0][3] + ty * matrix_[1][3] + tz * matrix_[2][3];
1201   return *this;
1202 }
1203 
PostTranslate(double tx,double ty)1204 TransformationMatrix& TransformationMatrix::PostTranslate(double tx,
1205                                                           double ty) {
1206   if (tx != 0) {
1207     matrix_[0][0] += matrix_[0][3] * tx;
1208     matrix_[1][0] += matrix_[1][3] * tx;
1209     matrix_[2][0] += matrix_[2][3] * tx;
1210     matrix_[3][0] += matrix_[3][3] * tx;
1211   }
1212 
1213   if (ty != 0) {
1214     matrix_[0][1] += matrix_[0][3] * ty;
1215     matrix_[1][1] += matrix_[1][3] * ty;
1216     matrix_[2][1] += matrix_[2][3] * ty;
1217     matrix_[3][1] += matrix_[3][3] * ty;
1218   }
1219 
1220   return *this;
1221 }
1222 
PostTranslate3d(double tx,double ty,double tz)1223 TransformationMatrix& TransformationMatrix::PostTranslate3d(double tx,
1224                                                             double ty,
1225                                                             double tz) {
1226   PostTranslate(tx, ty);
1227   if (tz != 0) {
1228     matrix_[0][2] += matrix_[0][3] * tz;
1229     matrix_[1][2] += matrix_[1][3] * tz;
1230     matrix_[2][2] += matrix_[2][3] * tz;
1231     matrix_[3][2] += matrix_[3][3] * tz;
1232   }
1233 
1234   return *this;
1235 }
1236 
Skew(double sx,double sy)1237 TransformationMatrix& TransformationMatrix::Skew(double sx, double sy) {
1238   // angles are in degrees. Switch to radians
1239   sx = deg2rad(sx);
1240   sy = deg2rad(sy);
1241 
1242   TransformationMatrix mat;
1243   mat.matrix_[0][1] =
1244       std::tan(sy);  // note that the y shear goes in the first row
1245   mat.matrix_[1][0] = std::tan(sx);  // and the x shear in the second row
1246 
1247   Multiply(mat);
1248   return *this;
1249 }
1250 
ApplyPerspective(double p)1251 TransformationMatrix& TransformationMatrix::ApplyPerspective(double p) {
1252   TransformationMatrix mat;
1253   if (p != 0)
1254     mat.matrix_[2][3] = -1 / p;
1255 
1256   Multiply(mat);
1257   return *this;
1258 }
1259 
ApplyTransformOrigin(double x,double y,double z)1260 TransformationMatrix& TransformationMatrix::ApplyTransformOrigin(double x,
1261                                                                  double y,
1262                                                                  double z) {
1263   PostTranslate3d(x, y, z);
1264   Translate3d(-x, -y, -z);
1265   return *this;
1266 }
1267 
Zoom(double zoom_factor)1268 TransformationMatrix& TransformationMatrix::Zoom(double zoom_factor) {
1269   matrix_[0][3] /= zoom_factor;
1270   matrix_[1][3] /= zoom_factor;
1271   matrix_[2][3] /= zoom_factor;
1272   matrix_[3][0] *= zoom_factor;
1273   matrix_[3][1] *= zoom_factor;
1274   matrix_[3][2] *= zoom_factor;
1275   return *this;
1276 }
1277 
1278 // Calculates *this = *this * mat.
1279 // Note: As we are using the column vector convention, i.e. T * P,
1280 // (lhs * rhs) * P = lhs * (rhs * P)
1281 // That means from the perspective of the transformed object, the combined
1282 // transform is equal to applying the rhs(mat) first, then lhs(*this) second.
1283 // For example:
1284 // TransformationMatrix lhs; lhs.Rotate(90.f);
1285 // TransformationMatrix rhs; rhs.Translate(12.f, 34.f);
1286 // TransformationMatrix prod = lhs;
1287 // prod.Multiply(rhs);
1288 // lhs.MapPoint(rhs.MapPoint(p)) == prod.MapPoint(p)
1289 // Also 'prod' corresponds to CSS transform:rotateZ(90deg)translate(12px,34px).
Multiply(const TransformationMatrix & mat)1290 TransformationMatrix& TransformationMatrix::Multiply(
1291     const TransformationMatrix& mat) {
1292 #if defined(ARCH_CPU_ARM64)
1293   double* left_matrix = &(matrix_[0][0]);
1294   const double* right_matrix = &(mat.matrix_[0][0]);
1295   asm volatile(
1296       // Load this->matrix_ to v24 - v31.
1297       // Load mat.matrix_ to v16 - v23.
1298       // Result: *this = *this * mat
1299       // | v0 v2 v4 v6 |   | v24 v26 v28 v30 |   | v16 v18 v20 v22 |
1300       // |             | = |                 | * |                 |
1301       // | v1 v3 v5 v7 |   | v25 v27 v29 v31 |   | v17 v19 v21 v23 |
1302       // |             |   |                 |   |                 |
1303       "mov x9, %[left_matrix]   \t\n"
1304       "ld1 {v16.2d - v19.2d}, [%[right_matrix]], 64  \t\n"
1305       "ld1 {v20.2d - v23.2d}, [%[right_matrix]]      \t\n"
1306       "ld1 {v24.2d - v27.2d}, [%[left_matrix]], 64 \t\n"
1307       "ld1 {v28.2d - v31.2d}, [%[left_matrix]]     \t\n"
1308 
1309       "fmul v0.2d, v24.2d, v16.d[0]  \t\n"
1310       "fmul v1.2d, v25.2d, v16.d[0]  \t\n"
1311       "fmul v2.2d, v24.2d, v18.d[0]  \t\n"
1312       "fmul v3.2d, v25.2d, v18.d[0]  \t\n"
1313       "fmul v4.2d, v24.2d, v20.d[0]  \t\n"
1314       "fmul v5.2d, v25.2d, v20.d[0]  \t\n"
1315       "fmul v6.2d, v24.2d, v22.d[0]  \t\n"
1316       "fmul v7.2d, v25.2d, v22.d[0]  \t\n"
1317 
1318       "fmla v0.2d, v26.2d, v16.d[1]  \t\n"
1319       "fmla v1.2d, v27.2d, v16.d[1]  \t\n"
1320       "fmla v2.2d, v26.2d, v18.d[1]  \t\n"
1321       "fmla v3.2d, v27.2d, v18.d[1]  \t\n"
1322       "fmla v4.2d, v26.2d, v20.d[1]  \t\n"
1323       "fmla v5.2d, v27.2d, v20.d[1]  \t\n"
1324       "fmla v6.2d, v26.2d, v22.d[1]  \t\n"
1325       "fmla v7.2d, v27.2d, v22.d[1]  \t\n"
1326 
1327       "fmla v0.2d, v28.2d, v17.d[0]  \t\n"
1328       "fmla v1.2d, v29.2d, v17.d[0]  \t\n"
1329       "fmla v2.2d, v28.2d, v19.d[0]  \t\n"
1330       "fmla v3.2d, v29.2d, v19.d[0]  \t\n"
1331       "fmla v4.2d, v28.2d, v21.d[0]  \t\n"
1332       "fmla v5.2d, v29.2d, v21.d[0]  \t\n"
1333       "fmla v6.2d, v28.2d, v23.d[0]  \t\n"
1334       "fmla v7.2d, v29.2d, v23.d[0]  \t\n"
1335 
1336       "fmla v0.2d, v30.2d, v17.d[1]  \t\n"
1337       "fmla v1.2d, v31.2d, v17.d[1]  \t\n"
1338       "fmla v2.2d, v30.2d, v19.d[1]  \t\n"
1339       "fmla v3.2d, v31.2d, v19.d[1]  \t\n"
1340       "fmla v4.2d, v30.2d, v21.d[1]  \t\n"
1341       "fmla v5.2d, v31.2d, v21.d[1]  \t\n"
1342       "fmla v6.2d, v30.2d, v23.d[1]  \t\n"
1343       "fmla v7.2d, v31.2d, v23.d[1]  \t\n"
1344 
1345       "st1 {v0.2d - v3.2d}, [x9], 64 \t\n"
1346       "st1 {v4.2d - v7.2d}, [x9]     \t\n"
1347       : [right_matrix] "+r"(right_matrix), [left_matrix] "+r"(left_matrix)
1348       :
1349       : "memory", "x9", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
1350         "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", "v0", "v1",
1351         "v2", "v3", "v4", "v5", "v6", "v7");
1352 #elif defined(HAVE_MIPS_MSA_INTRINSICS)
1353   v2f64 v_right_m0, v_right_m1, v_right_m2, v_right_m3, v_right_m4, v_right_m5,
1354       v_right_m6, v_right_m7;
1355   v2f64 v_left_m0, v_left_m1, v_left_m2, v_left_m3, v_left_m4, v_left_m5,
1356       v_left_m6, v_left_m7;
1357   v2f64 v_tmp_m0, v_tmp_m1, v_tmp_m2, v_tmp_m3;
1358 
1359   v_left_m0 = LD_DP(&(matrix_[0][0]));
1360   v_left_m1 = LD_DP(&(matrix_[0][2]));
1361   v_left_m2 = LD_DP(&(matrix_[1][0]));
1362   v_left_m3 = LD_DP(&(matrix_[1][2]));
1363   v_left_m4 = LD_DP(&(matrix_[2][0]));
1364   v_left_m5 = LD_DP(&(matrix_[2][2]));
1365   v_left_m6 = LD_DP(&(matrix_[3][0]));
1366   v_left_m7 = LD_DP(&(matrix_[3][2]));
1367 
1368   v_right_m0 = LD_DP(&(mat.matrix_[0][0]));
1369   v_right_m2 = LD_DP(&(mat.matrix_[0][2]));
1370   v_right_m4 = LD_DP(&(mat.matrix_[1][0]));
1371   v_right_m6 = LD_DP(&(mat.matrix_[1][2]));
1372 
1373   v_right_m1 = (v2f64)__msa_splati_d((v2i64)v_right_m0, 1);
1374   v_right_m0 = (v2f64)__msa_splati_d((v2i64)v_right_m0, 0);
1375   v_right_m3 = (v2f64)__msa_splati_d((v2i64)v_right_m2, 1);
1376   v_right_m2 = (v2f64)__msa_splati_d((v2i64)v_right_m2, 0);
1377   v_right_m5 = (v2f64)__msa_splati_d((v2i64)v_right_m4, 1);
1378   v_right_m4 = (v2f64)__msa_splati_d((v2i64)v_right_m4, 0);
1379   v_right_m7 = (v2f64)__msa_splati_d((v2i64)v_right_m6, 1);
1380   v_right_m6 = (v2f64)__msa_splati_d((v2i64)v_right_m6, 0);
1381 
1382   v_tmp_m0 = v_right_m0 * v_left_m0;
1383   v_tmp_m1 = v_right_m0 * v_left_m1;
1384   v_tmp_m0 += v_right_m1 * v_left_m2;
1385   v_tmp_m1 += v_right_m1 * v_left_m3;
1386   v_tmp_m0 += v_right_m2 * v_left_m4;
1387   v_tmp_m1 += v_right_m2 * v_left_m5;
1388   v_tmp_m0 += v_right_m3 * v_left_m6;
1389   v_tmp_m1 += v_right_m3 * v_left_m7;
1390 
1391   v_tmp_m2 = v_right_m4 * v_left_m0;
1392   v_tmp_m3 = v_right_m4 * v_left_m1;
1393   v_tmp_m2 += v_right_m5 * v_left_m2;
1394   v_tmp_m3 += v_right_m5 * v_left_m3;
1395   v_tmp_m2 += v_right_m6 * v_left_m4;
1396   v_tmp_m3 += v_right_m6 * v_left_m5;
1397   v_tmp_m2 += v_right_m7 * v_left_m6;
1398   v_tmp_m3 += v_right_m7 * v_left_m7;
1399 
1400   v_right_m0 = LD_DP(&(mat.matrix_[2][0]));
1401   v_right_m2 = LD_DP(&(mat.matrix_[2][2]));
1402   v_right_m4 = LD_DP(&(mat.matrix_[3][0]));
1403   v_right_m6 = LD_DP(&(mat.matrix_[3][2]));
1404 
1405   ST_DP(v_tmp_m0, &(matrix_[0][0]));
1406   ST_DP(v_tmp_m1, &(matrix_[0][2]));
1407   ST_DP(v_tmp_m2, &(matrix_[1][0]));
1408   ST_DP(v_tmp_m3, &(matrix_[1][2]));
1409 
1410   v_right_m1 = (v2f64)__msa_splati_d((v2i64)v_right_m0, 1);
1411   v_right_m0 = (v2f64)__msa_splati_d((v2i64)v_right_m0, 0);
1412   v_right_m3 = (v2f64)__msa_splati_d((v2i64)v_right_m2, 1);
1413   v_right_m2 = (v2f64)__msa_splati_d((v2i64)v_right_m2, 0);
1414   v_right_m5 = (v2f64)__msa_splati_d((v2i64)v_right_m4, 1);
1415   v_right_m4 = (v2f64)__msa_splati_d((v2i64)v_right_m4, 0);
1416   v_right_m7 = (v2f64)__msa_splati_d((v2i64)v_right_m6, 1);
1417   v_right_m6 = (v2f64)__msa_splati_d((v2i64)v_right_m6, 0);
1418 
1419   v_tmp_m0 = v_right_m0 * v_left_m0;
1420   v_tmp_m1 = v_right_m0 * v_left_m1;
1421   v_tmp_m0 += v_right_m1 * v_left_m2;
1422   v_tmp_m1 += v_right_m1 * v_left_m3;
1423   v_tmp_m0 += v_right_m2 * v_left_m4;
1424   v_tmp_m1 += v_right_m2 * v_left_m5;
1425   v_tmp_m0 += v_right_m3 * v_left_m6;
1426   v_tmp_m1 += v_right_m3 * v_left_m7;
1427 
1428   v_tmp_m2 = v_right_m4 * v_left_m0;
1429   v_tmp_m3 = v_right_m4 * v_left_m1;
1430   v_tmp_m2 += v_right_m5 * v_left_m2;
1431   v_tmp_m3 += v_right_m5 * v_left_m3;
1432   v_tmp_m2 += v_right_m6 * v_left_m4;
1433   v_tmp_m3 += v_right_m6 * v_left_m5;
1434   v_tmp_m2 += v_right_m7 * v_left_m6;
1435   v_tmp_m3 += v_right_m7 * v_left_m7;
1436 
1437   ST_DP(v_tmp_m0, &(matrix_[2][0]));
1438   ST_DP(v_tmp_m1, &(matrix_[2][2]));
1439   ST_DP(v_tmp_m2, &(matrix_[3][0]));
1440   ST_DP(v_tmp_m3, &(matrix_[3][2]));
1441 #elif defined(ARCH_CPU_X86_64)
1442   // x86_64 has 16 XMM registers which is enough to do the multiplication fully
1443   // in registers.
1444   __m128d matrix_block_a = _mm_loadu_pd(&(matrix_[0][0]));
1445   __m128d matrix_block_c = _mm_loadu_pd(&(matrix_[1][0]));
1446   __m128d matrix_block_e = _mm_loadu_pd(&(matrix_[2][0]));
1447   __m128d matrix_block_g = _mm_loadu_pd(&(matrix_[3][0]));
1448 
1449   // First column.
1450   __m128d other_matrix_first_param = _mm_set1_pd(mat.matrix_[0][0]);
1451   __m128d other_matrix_second_param = _mm_set1_pd(mat.matrix_[0][1]);
1452   __m128d other_matrix_third_param = _mm_set1_pd(mat.matrix_[0][2]);
1453   __m128d other_matrix_fourth_param = _mm_set1_pd(mat.matrix_[0][3]);
1454 
1455   // output00 and output01.
1456   __m128d accumulator = _mm_mul_pd(matrix_block_a, other_matrix_first_param);
1457   __m128d temp1 = _mm_mul_pd(matrix_block_c, other_matrix_second_param);
1458   __m128d temp2 = _mm_mul_pd(matrix_block_e, other_matrix_third_param);
1459   __m128d temp3 = _mm_mul_pd(matrix_block_g, other_matrix_fourth_param);
1460 
1461   __m128d matrix_block_b = _mm_loadu_pd(&(matrix_[0][2]));
1462   __m128d matrix_block_d = _mm_loadu_pd(&(matrix_[1][2]));
1463   __m128d matrix_block_f = _mm_loadu_pd(&(matrix_[2][2]));
1464   __m128d matrix_block_h = _mm_loadu_pd(&(matrix_[3][2]));
1465 
1466   accumulator = _mm_add_pd(accumulator, temp1);
1467   accumulator = _mm_add_pd(accumulator, temp2);
1468   accumulator = _mm_add_pd(accumulator, temp3);
1469   _mm_storeu_pd(&matrix_[0][0], accumulator);
1470 
1471   // output02 and output03.
1472   accumulator = _mm_mul_pd(matrix_block_b, other_matrix_first_param);
1473   temp1 = _mm_mul_pd(matrix_block_d, other_matrix_second_param);
1474   temp2 = _mm_mul_pd(matrix_block_f, other_matrix_third_param);
1475   temp3 = _mm_mul_pd(matrix_block_h, other_matrix_fourth_param);
1476 
1477   accumulator = _mm_add_pd(accumulator, temp1);
1478   accumulator = _mm_add_pd(accumulator, temp2);
1479   accumulator = _mm_add_pd(accumulator, temp3);
1480   _mm_storeu_pd(&matrix_[0][2], accumulator);
1481 
1482   // Second column.
1483   other_matrix_first_param = _mm_set1_pd(mat.matrix_[1][0]);
1484   other_matrix_second_param = _mm_set1_pd(mat.matrix_[1][1]);
1485   other_matrix_third_param = _mm_set1_pd(mat.matrix_[1][2]);
1486   other_matrix_fourth_param = _mm_set1_pd(mat.matrix_[1][3]);
1487 
1488   // output10 and output11.
1489   accumulator = _mm_mul_pd(matrix_block_a, other_matrix_first_param);
1490   temp1 = _mm_mul_pd(matrix_block_c, other_matrix_second_param);
1491   temp2 = _mm_mul_pd(matrix_block_e, other_matrix_third_param);
1492   temp3 = _mm_mul_pd(matrix_block_g, other_matrix_fourth_param);
1493 
1494   accumulator = _mm_add_pd(accumulator, temp1);
1495   accumulator = _mm_add_pd(accumulator, temp2);
1496   accumulator = _mm_add_pd(accumulator, temp3);
1497   _mm_storeu_pd(&matrix_[1][0], accumulator);
1498 
1499   // output12 and output13.
1500   accumulator = _mm_mul_pd(matrix_block_b, other_matrix_first_param);
1501   temp1 = _mm_mul_pd(matrix_block_d, other_matrix_second_param);
1502   temp2 = _mm_mul_pd(matrix_block_f, other_matrix_third_param);
1503   temp3 = _mm_mul_pd(matrix_block_h, other_matrix_fourth_param);
1504 
1505   accumulator = _mm_add_pd(accumulator, temp1);
1506   accumulator = _mm_add_pd(accumulator, temp2);
1507   accumulator = _mm_add_pd(accumulator, temp3);
1508   _mm_storeu_pd(&matrix_[1][2], accumulator);
1509 
1510   // Third column.
1511   other_matrix_first_param = _mm_set1_pd(mat.matrix_[2][0]);
1512   other_matrix_second_param = _mm_set1_pd(mat.matrix_[2][1]);
1513   other_matrix_third_param = _mm_set1_pd(mat.matrix_[2][2]);
1514   other_matrix_fourth_param = _mm_set1_pd(mat.matrix_[2][3]);
1515 
1516   // output20 and output21.
1517   accumulator = _mm_mul_pd(matrix_block_a, other_matrix_first_param);
1518   temp1 = _mm_mul_pd(matrix_block_c, other_matrix_second_param);
1519   temp2 = _mm_mul_pd(matrix_block_e, other_matrix_third_param);
1520   temp3 = _mm_mul_pd(matrix_block_g, other_matrix_fourth_param);
1521 
1522   accumulator = _mm_add_pd(accumulator, temp1);
1523   accumulator = _mm_add_pd(accumulator, temp2);
1524   accumulator = _mm_add_pd(accumulator, temp3);
1525   _mm_storeu_pd(&matrix_[2][0], accumulator);
1526 
1527   // output22 and output23.
1528   accumulator = _mm_mul_pd(matrix_block_b, other_matrix_first_param);
1529   temp1 = _mm_mul_pd(matrix_block_d, other_matrix_second_param);
1530   temp2 = _mm_mul_pd(matrix_block_f, other_matrix_third_param);
1531   temp3 = _mm_mul_pd(matrix_block_h, other_matrix_fourth_param);
1532 
1533   accumulator = _mm_add_pd(accumulator, temp1);
1534   accumulator = _mm_add_pd(accumulator, temp2);
1535   accumulator = _mm_add_pd(accumulator, temp3);
1536   _mm_storeu_pd(&matrix_[2][2], accumulator);
1537 
1538   // Fourth column.
1539   other_matrix_first_param = _mm_set1_pd(mat.matrix_[3][0]);
1540   other_matrix_second_param = _mm_set1_pd(mat.matrix_[3][1]);
1541   other_matrix_third_param = _mm_set1_pd(mat.matrix_[3][2]);
1542   other_matrix_fourth_param = _mm_set1_pd(mat.matrix_[3][3]);
1543 
1544   // output30 and output31.
1545   accumulator = _mm_mul_pd(matrix_block_a, other_matrix_first_param);
1546   temp1 = _mm_mul_pd(matrix_block_c, other_matrix_second_param);
1547   temp2 = _mm_mul_pd(matrix_block_e, other_matrix_third_param);
1548   temp3 = _mm_mul_pd(matrix_block_g, other_matrix_fourth_param);
1549 
1550   accumulator = _mm_add_pd(accumulator, temp1);
1551   accumulator = _mm_add_pd(accumulator, temp2);
1552   accumulator = _mm_add_pd(accumulator, temp3);
1553   _mm_storeu_pd(&matrix_[3][0], accumulator);
1554 
1555   // output32 and output33.
1556   accumulator = _mm_mul_pd(matrix_block_b, other_matrix_first_param);
1557   temp1 = _mm_mul_pd(matrix_block_d, other_matrix_second_param);
1558   temp2 = _mm_mul_pd(matrix_block_f, other_matrix_third_param);
1559   temp3 = _mm_mul_pd(matrix_block_h, other_matrix_fourth_param);
1560 
1561   accumulator = _mm_add_pd(accumulator, temp1);
1562   accumulator = _mm_add_pd(accumulator, temp2);
1563   accumulator = _mm_add_pd(accumulator, temp3);
1564   _mm_storeu_pd(&matrix_[3][2], accumulator);
1565 #else
1566   Matrix4 tmp;
1567 
1568   tmp[0][0] =
1569       (mat.matrix_[0][0] * matrix_[0][0] + mat.matrix_[0][1] * matrix_[1][0] +
1570        mat.matrix_[0][2] * matrix_[2][0] + mat.matrix_[0][3] * matrix_[3][0]);
1571   tmp[0][1] =
1572       (mat.matrix_[0][0] * matrix_[0][1] + mat.matrix_[0][1] * matrix_[1][1] +
1573        mat.matrix_[0][2] * matrix_[2][1] + mat.matrix_[0][3] * matrix_[3][1]);
1574   tmp[0][2] =
1575       (mat.matrix_[0][0] * matrix_[0][2] + mat.matrix_[0][1] * matrix_[1][2] +
1576        mat.matrix_[0][2] * matrix_[2][2] + mat.matrix_[0][3] * matrix_[3][2]);
1577   tmp[0][3] =
1578       (mat.matrix_[0][0] * matrix_[0][3] + mat.matrix_[0][1] * matrix_[1][3] +
1579        mat.matrix_[0][2] * matrix_[2][3] + mat.matrix_[0][3] * matrix_[3][3]);
1580 
1581   tmp[1][0] =
1582       (mat.matrix_[1][0] * matrix_[0][0] + mat.matrix_[1][1] * matrix_[1][0] +
1583        mat.matrix_[1][2] * matrix_[2][0] + mat.matrix_[1][3] * matrix_[3][0]);
1584   tmp[1][1] =
1585       (mat.matrix_[1][0] * matrix_[0][1] + mat.matrix_[1][1] * matrix_[1][1] +
1586        mat.matrix_[1][2] * matrix_[2][1] + mat.matrix_[1][3] * matrix_[3][1]);
1587   tmp[1][2] =
1588       (mat.matrix_[1][0] * matrix_[0][2] + mat.matrix_[1][1] * matrix_[1][2] +
1589        mat.matrix_[1][2] * matrix_[2][2] + mat.matrix_[1][3] * matrix_[3][2]);
1590   tmp[1][3] =
1591       (mat.matrix_[1][0] * matrix_[0][3] + mat.matrix_[1][1] * matrix_[1][3] +
1592        mat.matrix_[1][2] * matrix_[2][3] + mat.matrix_[1][3] * matrix_[3][3]);
1593 
1594   tmp[2][0] =
1595       (mat.matrix_[2][0] * matrix_[0][0] + mat.matrix_[2][1] * matrix_[1][0] +
1596        mat.matrix_[2][2] * matrix_[2][0] + mat.matrix_[2][3] * matrix_[3][0]);
1597   tmp[2][1] =
1598       (mat.matrix_[2][0] * matrix_[0][1] + mat.matrix_[2][1] * matrix_[1][1] +
1599        mat.matrix_[2][2] * matrix_[2][1] + mat.matrix_[2][3] * matrix_[3][1]);
1600   tmp[2][2] =
1601       (mat.matrix_[2][0] * matrix_[0][2] + mat.matrix_[2][1] * matrix_[1][2] +
1602        mat.matrix_[2][2] * matrix_[2][2] + mat.matrix_[2][3] * matrix_[3][2]);
1603   tmp[2][3] =
1604       (mat.matrix_[2][0] * matrix_[0][3] + mat.matrix_[2][1] * matrix_[1][3] +
1605        mat.matrix_[2][2] * matrix_[2][3] + mat.matrix_[2][3] * matrix_[3][3]);
1606 
1607   tmp[3][0] =
1608       (mat.matrix_[3][0] * matrix_[0][0] + mat.matrix_[3][1] * matrix_[1][0] +
1609        mat.matrix_[3][2] * matrix_[2][0] + mat.matrix_[3][3] * matrix_[3][0]);
1610   tmp[3][1] =
1611       (mat.matrix_[3][0] * matrix_[0][1] + mat.matrix_[3][1] * matrix_[1][1] +
1612        mat.matrix_[3][2] * matrix_[2][1] + mat.matrix_[3][3] * matrix_[3][1]);
1613   tmp[3][2] =
1614       (mat.matrix_[3][0] * matrix_[0][2] + mat.matrix_[3][1] * matrix_[1][2] +
1615        mat.matrix_[3][2] * matrix_[2][2] + mat.matrix_[3][3] * matrix_[3][2]);
1616   tmp[3][3] =
1617       (mat.matrix_[3][0] * matrix_[0][3] + mat.matrix_[3][1] * matrix_[1][3] +
1618        mat.matrix_[3][2] * matrix_[2][3] + mat.matrix_[3][3] * matrix_[3][3]);
1619 
1620   SetMatrix(tmp);
1621 #endif
1622   return *this;
1623 }
1624 
MultVecMatrix(double x,double y,double & result_x,double & result_y) const1625 void TransformationMatrix::MultVecMatrix(double x,
1626                                          double y,
1627                                          double& result_x,
1628                                          double& result_y) const {
1629   result_x = matrix_[3][0] + x * matrix_[0][0] + y * matrix_[1][0];
1630   result_y = matrix_[3][1] + x * matrix_[0][1] + y * matrix_[1][1];
1631   double w = matrix_[3][3] + x * matrix_[0][3] + y * matrix_[1][3];
1632   if (w != 1 && w != 0) {
1633     result_x /= w;
1634     result_y /= w;
1635   }
1636 }
1637 
MultVecMatrix(double x,double y,double z,double & result_x,double & result_y,double & result_z) const1638 void TransformationMatrix::MultVecMatrix(double x,
1639                                          double y,
1640                                          double z,
1641                                          double& result_x,
1642                                          double& result_y,
1643                                          double& result_z) const {
1644   result_x =
1645       matrix_[3][0] + x * matrix_[0][0] + y * matrix_[1][0] + z * matrix_[2][0];
1646   result_y =
1647       matrix_[3][1] + x * matrix_[0][1] + y * matrix_[1][1] + z * matrix_[2][1];
1648   result_z =
1649       matrix_[3][2] + x * matrix_[0][2] + y * matrix_[1][2] + z * matrix_[2][2];
1650   double w =
1651       matrix_[3][3] + x * matrix_[0][3] + y * matrix_[1][3] + z * matrix_[2][3];
1652   if (w != 1 && w != 0) {
1653     result_x /= w;
1654     result_y /= w;
1655     result_z /= w;
1656   }
1657 }
1658 
IsInvertible() const1659 bool TransformationMatrix::IsInvertible() const {
1660   return IsIdentityOrTranslation() || blink::Determinant4x4(matrix_) != 0;
1661 }
1662 
Inverse() const1663 TransformationMatrix TransformationMatrix::Inverse() const {
1664   if (IsIdentityOrTranslation()) {
1665     // identity matrix
1666     if (matrix_[3][0] == 0 && matrix_[3][1] == 0 && matrix_[3][2] == 0)
1667       return TransformationMatrix();
1668 
1669     // translation
1670     return TransformationMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
1671                                 -matrix_[3][0], -matrix_[3][1], -matrix_[3][2],
1672                                 1);
1673   }
1674 
1675   TransformationMatrix inv_mat;
1676   bool inverted = blink::Inverse(matrix_, inv_mat.matrix_);
1677   if (!inverted)
1678     return TransformationMatrix();
1679 
1680   return inv_mat;
1681 }
1682 
MakeAffine()1683 void TransformationMatrix::MakeAffine() {
1684   matrix_[0][2] = 0;
1685   matrix_[0][3] = 0;
1686 
1687   matrix_[1][2] = 0;
1688   matrix_[1][3] = 0;
1689 
1690   matrix_[2][0] = 0;
1691   matrix_[2][1] = 0;
1692   matrix_[2][2] = 1;
1693   matrix_[2][3] = 0;
1694 
1695   matrix_[3][2] = 0;
1696   matrix_[3][3] = 1;
1697 }
1698 
ToAffineTransform() const1699 AffineTransform TransformationMatrix::ToAffineTransform() const {
1700   return AffineTransform(matrix_[0][0], matrix_[0][1], matrix_[1][0],
1701                          matrix_[1][1], matrix_[3][0], matrix_[3][1]);
1702 }
1703 
FlattenTo2d()1704 void TransformationMatrix::FlattenTo2d() {
1705   matrix_[2][0] = 0;
1706   matrix_[2][1] = 0;
1707   matrix_[0][2] = 0;
1708   matrix_[1][2] = 0;
1709   matrix_[2][2] = 1;
1710   matrix_[3][2] = 0;
1711   matrix_[2][3] = 0;
1712 }
1713 
BlendFloat(double & from,double to,double progress)1714 static inline void BlendFloat(double& from, double to, double progress) {
1715   if (from != to)
1716     from = from + (to - from) * progress;
1717 }
1718 
Is2dTransform() const1719 bool TransformationMatrix::Is2dTransform() const {
1720   if (!IsFlat())
1721     return false;
1722 
1723   // Check perspective.
1724   if (matrix_[0][3] != 0 || matrix_[1][3] != 0 || matrix_[2][3] != 0 ||
1725       matrix_[3][3] != 1)
1726     return false;
1727 
1728   return true;
1729 }
1730 
Blend(const TransformationMatrix & from,double progress)1731 void TransformationMatrix::Blend(const TransformationMatrix& from,
1732                                  double progress) {
1733   if (from.IsIdentity() && IsIdentity())
1734     return;
1735 
1736   if (from.Is2dTransform() && Is2dTransform()) {
1737     Blend2D(from, progress);
1738     return;
1739   }
1740 
1741   // decompose
1742   DecomposedType from_decomp;
1743   DecomposedType to_decomp;
1744   if (!from.Decompose(from_decomp) || !Decompose(to_decomp)) {
1745     if (progress < 0.5)
1746       *this = from;
1747     return;
1748   }
1749 
1750   // interpolate
1751   BlendFloat(from_decomp.scale_x, to_decomp.scale_x, progress);
1752   BlendFloat(from_decomp.scale_y, to_decomp.scale_y, progress);
1753   BlendFloat(from_decomp.scale_z, to_decomp.scale_z, progress);
1754   BlendFloat(from_decomp.skew_xy, to_decomp.skew_xy, progress);
1755   BlendFloat(from_decomp.skew_xz, to_decomp.skew_xz, progress);
1756   BlendFloat(from_decomp.skew_yz, to_decomp.skew_yz, progress);
1757   BlendFloat(from_decomp.translate_x, to_decomp.translate_x, progress);
1758   BlendFloat(from_decomp.translate_y, to_decomp.translate_y, progress);
1759   BlendFloat(from_decomp.translate_z, to_decomp.translate_z, progress);
1760   BlendFloat(from_decomp.perspective_x, to_decomp.perspective_x, progress);
1761   BlendFloat(from_decomp.perspective_y, to_decomp.perspective_y, progress);
1762   BlendFloat(from_decomp.perspective_z, to_decomp.perspective_z, progress);
1763   BlendFloat(from_decomp.perspective_w, to_decomp.perspective_w, progress);
1764 
1765   Slerp(from_decomp, to_decomp, progress);
1766 
1767   // recompose
1768   Recompose(from_decomp);
1769 }
1770 
Blend2D(const TransformationMatrix & from,double progress)1771 void TransformationMatrix::Blend2D(const TransformationMatrix& from,
1772                                    double progress) {
1773   // Decompose into scale, rotate, translate and skew transforms.
1774   Decomposed2dType from_decomp;
1775   Decomposed2dType to_decomp;
1776   if (!from.Decompose2D(from_decomp) || !Decompose2D(to_decomp)) {
1777     if (progress < 0.5)
1778       *this = from;
1779     return;
1780   }
1781 
1782   // Take the shorter of the clockwise or counter-clockwise paths.
1783   double rotation = abs(from_decomp.angle - to_decomp.angle);
1784   DCHECK(rotation < 2 * M_PI);
1785   if (rotation > M_PI) {
1786     if (from_decomp.angle > to_decomp.angle) {
1787       from_decomp.angle -= 2 * M_PI;
1788     } else {
1789       to_decomp.angle -= 2 * M_PI;
1790     }
1791   }
1792 
1793   // Interpolate.
1794   BlendFloat(from_decomp.scale_x, to_decomp.scale_x, progress);
1795   BlendFloat(from_decomp.scale_y, to_decomp.scale_y, progress);
1796   BlendFloat(from_decomp.skew_xy, to_decomp.skew_xy, progress);
1797   BlendFloat(from_decomp.translate_x, to_decomp.translate_x, progress);
1798   BlendFloat(from_decomp.translate_y, to_decomp.translate_y, progress);
1799   BlendFloat(from_decomp.angle, to_decomp.angle, progress);
1800 
1801   // Recompose.
1802   Recompose2D(from_decomp);
1803 }
1804 
Decompose(DecomposedType & decomp) const1805 bool TransformationMatrix::Decompose(DecomposedType& decomp) const {
1806   if (IsIdentity()) {
1807     memset(&decomp, 0, sizeof(decomp));
1808     decomp.perspective_w = 1;
1809     decomp.scale_x = 1;
1810     decomp.scale_y = 1;
1811     decomp.scale_z = 1;
1812   }
1813 
1814   if (!blink::Decompose(matrix_, decomp))
1815     return false;
1816   return true;
1817 }
1818 
1819 // Decompose a 2D transformation matrix of the form:
1820 // [m11 m21 0 m41]
1821 // [m12 m22 0 m42]
1822 // [ 0   0  1  0 ]
1823 // [ 0   0  0  1 ]
1824 //
1825 // The decomposition is of the form:
1826 // M = translate * rotate * skew * scale
1827 //     [1 0 0 Tx] [cos(R) -sin(R) 0 0] [1 K 0 0] [Sx 0  0 0]
1828 //   = [0 1 0 Ty] [sin(R)  cos(R) 0 0] [0 1 0 0] [0  Sy 0 0]
1829 //     [0 0 1 0 ] [  0       0    1 0] [0 0 1 0] [0  0  1 0]
1830 //     [0 0 0 1 ] [  0       0    0 1] [0 0 0 1] [0  0  0 1]
1831 //
Decompose2D(Decomposed2dType & decomp) const1832 bool TransformationMatrix::Decompose2D(Decomposed2dType& decomp) const {
1833   if (!Is2dTransform()) {
1834     LOG(ERROR) << "2-D decomposition cannot be performed on a 3-D transform.";
1835     return false;
1836   }
1837 
1838   double m11 = matrix_[0][0];
1839   double m21 = matrix_[1][0];
1840   double m12 = matrix_[0][1];
1841   double m22 = matrix_[1][1];
1842 
1843   double determinant = m11 * m22 - m12 * m21;
1844   // Test for matrix being singular.
1845   if (determinant == 0) {
1846     return false;
1847   }
1848 
1849   // Translation transform.
1850   // [m11 m21 0 m41]    [1 0 0 Tx] [m11 m21 0 0]
1851   // [m12 m22 0 m42]  = [0 1 0 Ty] [m12 m22 0 0]
1852   // [ 0   0  1  0 ]    [0 0 1 0 ] [ 0   0  1 0]
1853   // [ 0   0  0  1 ]    [0 0 0 1 ] [ 0   0  0 1]
1854   decomp.translate_x = matrix_[3][0];
1855   decomp.translate_y = matrix_[3][1];
1856 
1857   // For the remainder of the decomposition process, we can focus on the upper
1858   // 2x2 submatrix
1859   // [m11 m21] = [cos(R) -sin(R)] [1 K] [Sx 0 ]
1860   // [m12 m22]   [sin(R)  cos(R)] [0 1] [0  Sy]
1861   //           = [Sx*cos(R) Sy*(K*cos(R) - sin(R))]
1862   //             [Sx*sin(R) Sy*(K*sin(R) + cos(R))]
1863 
1864   // Determine sign of the x and y scale.
1865   decomp.scale_x = 1;
1866   decomp.scale_y = 1;
1867   if (determinant < 0) {
1868     // If the determinant is negative, we need to flip either the x or y scale.
1869     // Flipping both is equivalent to rotating by 180 degrees.
1870     // Flip the axis with the minimum unit vector dot product.
1871     if (m11 < m22) {
1872       decomp.scale_x = -decomp.scale_x;
1873     } else {
1874       decomp.scale_y = -decomp.scale_y;
1875     }
1876   }
1877 
1878   // X Scale.
1879   // m11^2 + m12^2 = Sx^2*(cos^2(R) + sin^2(R)) = Sx^2.
1880   // Sx = +/-sqrt(m11^2 + m22^2)
1881   decomp.scale_x *= sqrt(m11 * m11 + m12 * m12);
1882   m11 /= decomp.scale_x;
1883   m12 /= decomp.scale_x;
1884 
1885   // Post normalization, the submatrix is now of the form:
1886   // [m11 m21] = [cos(R)  Sy*(K*cos(R) - sin(R))]
1887   // [m12 m22]   [sin(R)  Sy*(K*sin(R) + cos(R))]
1888 
1889   // XY Shear.
1890   // m11 * m21 + m12 * m22 = Sy*K*cos^2(R) - Sy*sin(R)*cos(R) +
1891   //                         Sy*K*sin^2(R) + Sy*cos(R)*sin(R)
1892   //                       = Sy*K
1893   double scaledShear = m11 * m21 + m12 * m22;
1894   m21 -= m11 * scaledShear;
1895   m22 -= m12 * scaledShear;
1896 
1897   // Post normalization, the submatrix is now of the form:
1898   // [m11 m21] = [cos(R)  -Sy*sin(R)]
1899   // [m12 m22]   [sin(R)   Sy*cos(R)]
1900 
1901   // Y Scale.
1902   // Similar process to determining x-scale.
1903   decomp.scale_y *= sqrt(m21 * m21 + m22 * m22);
1904   m21 /= decomp.scale_y;
1905   m22 /= decomp.scale_y;
1906   decomp.skew_xy = scaledShear / decomp.scale_y;
1907 
1908   // Rotation transform.
1909   decomp.angle = atan2(m12, m11);
1910   return true;
1911 }
1912 
Recompose(const DecomposedType & decomp)1913 void TransformationMatrix::Recompose(const DecomposedType& decomp) {
1914   MakeIdentity();
1915 
1916   // first apply perspective
1917   matrix_[0][3] = decomp.perspective_x;
1918   matrix_[1][3] = decomp.perspective_y;
1919   matrix_[2][3] = decomp.perspective_z;
1920   matrix_[3][3] = decomp.perspective_w;
1921 
1922   // now translate
1923   Translate3d(decomp.translate_x, decomp.translate_y, decomp.translate_z);
1924 
1925   // apply rotation
1926   double xx = decomp.quaternion_x * decomp.quaternion_x;
1927   double xy = decomp.quaternion_x * decomp.quaternion_y;
1928   double xz = decomp.quaternion_x * decomp.quaternion_z;
1929   double xw = decomp.quaternion_x * decomp.quaternion_w;
1930   double yy = decomp.quaternion_y * decomp.quaternion_y;
1931   double yz = decomp.quaternion_y * decomp.quaternion_z;
1932   double yw = decomp.quaternion_y * decomp.quaternion_w;
1933   double zz = decomp.quaternion_z * decomp.quaternion_z;
1934   double zw = decomp.quaternion_z * decomp.quaternion_w;
1935 
1936   // Construct a composite rotation matrix from the quaternion values.
1937   // Arguments are in column order.
1938   // https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion
1939   TransformationMatrix rotation_matrix(1 - 2 * (yy + zz),     // Q_xx
1940                                        2 * (xy + zw),         // Q_yx
1941                                        2 * (xz - yw), 0,      // Q_zx
1942                                        2 * (xy - zw),         // Q_xy
1943                                        1 - 2 * (xx + zz),     // Q_yy
1944                                        2 * (yz + xw), 0,      // Q_zy
1945                                        2 * (xz + yw),         // Q_xz
1946                                        2 * (yz - xw),         // Q_yz
1947                                        1 - 2 * (xx + yy), 0,  // Q_zz
1948                                        0, 0, 0, 1);
1949 
1950   Multiply(rotation_matrix);
1951 
1952   // now apply skew
1953   if (decomp.skew_yz) {
1954     TransformationMatrix tmp;
1955     tmp.SetM32(decomp.skew_yz);
1956     Multiply(tmp);
1957   }
1958 
1959   if (decomp.skew_xz) {
1960     TransformationMatrix tmp;
1961     tmp.SetM31(decomp.skew_xz);
1962     Multiply(tmp);
1963   }
1964 
1965   if (decomp.skew_xy) {
1966     TransformationMatrix tmp;
1967     tmp.SetM21(decomp.skew_xy);
1968     Multiply(tmp);
1969   }
1970 
1971   // finally, apply scale
1972   Scale3d(decomp.scale_x, decomp.scale_y, decomp.scale_z);
1973 }
1974 
Recompose2D(const Decomposed2dType & decomp)1975 void TransformationMatrix::Recompose2D(const Decomposed2dType& decomp) {
1976   MakeIdentity();
1977 
1978   // Translate transform.
1979   SetM41(decomp.translate_x);
1980   SetM42(decomp.translate_y);
1981 
1982   // Rotate transform.
1983   double cosAngle = cos(decomp.angle);
1984   double sinAngle = sin(decomp.angle);
1985   SetM11(cosAngle);
1986   SetM21(-sinAngle);
1987   SetM12(sinAngle);
1988   SetM22(cosAngle);
1989 
1990   // skew transform.
1991   if (decomp.skew_xy) {
1992     TransformationMatrix skewTransform;
1993     skewTransform.SetM21(decomp.skew_xy);
1994     Multiply(skewTransform);
1995   }
1996 
1997   // Scale transform.
1998   Scale3d(decomp.scale_x, decomp.scale_y, 1);
1999 }
2000 
IsIntegerTranslation() const2001 bool TransformationMatrix::IsIntegerTranslation() const {
2002   if (!IsIdentityOrTranslation())
2003     return false;
2004 
2005   // Check for translate Z.
2006   if (matrix_[3][2])
2007     return false;
2008 
2009   // Check for non-integer translate X/Y.
2010   if (static_cast<int>(matrix_[3][0]) != matrix_[3][0] ||
2011       static_cast<int>(matrix_[3][1]) != matrix_[3][1])
2012     return false;
2013 
2014   return true;
2015 }
2016 
2017 // This is the same as gfx::Transform::Preserves2dAxisAlignment().
Preserves2dAxisAlignment() const2018 bool TransformationMatrix::Preserves2dAxisAlignment() const {
2019   // Check whether an axis aligned 2-dimensional rect would remain axis-aligned
2020   // after being transformed by this matrix (and implicitly projected by
2021   // dropping any non-zero z-values).
2022   //
2023   // The 4th column can be ignored because translations don't affect axis
2024   // alignment. The 3rd column can be ignored because we are assuming 2d
2025   // inputs, where z-values will be zero. The 3rd row can also be ignored
2026   // because we are assuming 2d outputs, and any resulting z-value is dropped
2027   // anyway. For the inner 2x2 portion, the only effects that keep a rect axis
2028   // aligned are (1) swapping axes and (2) scaling axes. This can be checked by
2029   // verifying only 1 element of every column and row is non-zero.  Degenerate
2030   // cases that project the x or y dimension to zero are considered to preserve
2031   // axis alignment.
2032   //
2033   // If the matrix does have perspective component that is affected by x or y
2034   // values: The current implementation conservatively assumes that axis
2035   // alignment is not preserved.
2036   bool has_x_or_y_perspective = M14() != 0 || M24() != 0;
2037   if (has_x_or_y_perspective)
2038     return false;
2039 
2040   // Use float epsilon here, not double, to round very small rotations back
2041   // to zero.
2042   constexpr double kEpsilon = std::numeric_limits<float>::epsilon();
2043 
2044   int num_non_zero_in_row_1 = 0;
2045   int num_non_zero_in_row_2 = 0;
2046   int num_non_zero_in_col_1 = 0;
2047   int num_non_zero_in_col_2 = 0;
2048   if (std::abs(M11()) > kEpsilon) {
2049     num_non_zero_in_col_1++;
2050     num_non_zero_in_row_1++;
2051   }
2052   if (std::abs(M12()) > kEpsilon) {
2053     num_non_zero_in_col_1++;
2054     num_non_zero_in_row_2++;
2055   }
2056   if (std::abs(M21()) > kEpsilon) {
2057     num_non_zero_in_col_2++;
2058     num_non_zero_in_row_1++;
2059   }
2060   if (std::abs(M22()) > kEpsilon) {
2061     num_non_zero_in_col_2++;
2062     num_non_zero_in_row_2++;
2063   }
2064 
2065   return num_non_zero_in_row_1 <= 1 && num_non_zero_in_row_2 <= 1 &&
2066          num_non_zero_in_col_1 <= 1 && num_non_zero_in_col_2 <= 1;
2067 }
2068 
ToColumnMajorFloatArray(FloatMatrix4 & result) const2069 void TransformationMatrix::ToColumnMajorFloatArray(FloatMatrix4& result) const {
2070   result[0] = M11();
2071   result[1] = M12();
2072   result[2] = M13();
2073   result[3] = M14();
2074   result[4] = M21();
2075   result[5] = M22();
2076   result[6] = M23();
2077   result[7] = M24();
2078   result[8] = M31();
2079   result[9] = M32();
2080   result[10] = M33();
2081   result[11] = M34();
2082   result[12] = M41();
2083   result[13] = M42();
2084   result[14] = M43();
2085   result[15] = M44();
2086 }
2087 
ToSkMatrix44(const TransformationMatrix & matrix)2088 SkMatrix44 TransformationMatrix::ToSkMatrix44(
2089     const TransformationMatrix& matrix) {
2090   SkMatrix44 ret(SkMatrix44::kUninitialized_Constructor);
2091   ret.set4x4(matrix.M11(), matrix.M12(), matrix.M13(), matrix.M14(),
2092              matrix.M21(), matrix.M22(), matrix.M23(), matrix.M24(),
2093              matrix.M31(), matrix.M32(), matrix.M33(), matrix.M34(),
2094              matrix.M41(), matrix.M42(), matrix.M43(), matrix.M44());
2095   return ret;
2096 }
2097 
ToTransform(const TransformationMatrix & matrix)2098 gfx::Transform TransformationMatrix::ToTransform(
2099     const TransformationMatrix& matrix) {
2100   return gfx::Transform(matrix.M11(), matrix.M21(), matrix.M31(), matrix.M41(),
2101                         matrix.M12(), matrix.M22(), matrix.M32(), matrix.M42(),
2102                         matrix.M13(), matrix.M23(), matrix.M33(), matrix.M43(),
2103                         matrix.M14(), matrix.M24(), matrix.M34(), matrix.M44());
2104 }
2105 
ToString(bool as_matrix) const2106 String TransformationMatrix::ToString(bool as_matrix) const {
2107   if (as_matrix) {
2108     // Return as a matrix in row-major order.
2109     return String::Format(
2110         "[%lg,%lg,%lg,%lg,\n%lg,%lg,%lg,%lg,\n%lg,%lg,%lg,%lg,\n%lg,%lg,%lg,%"
2111         "lg]",
2112         M11(), M21(), M31(), M41(), M12(), M22(), M32(), M42(), M13(), M23(),
2113         M33(), M43(), M14(), M24(), M34(), M44());
2114   }
2115 
2116   TransformationMatrix::DecomposedType decomposition;
2117   if (!Decompose(decomposition))
2118     return ToString(true) + " (degenerate)";
2119 
2120   if (IsIdentityOrTranslation()) {
2121     if (decomposition.translate_x == 0 && decomposition.translate_y == 0 &&
2122         decomposition.translate_z == 0)
2123       return "identity";
2124     return String::Format("translation(%lg,%lg,%lg)", decomposition.translate_x,
2125                           decomposition.translate_y, decomposition.translate_z);
2126   }
2127 
2128   return String::Format(
2129       "translation(%lg,%lg,%lg), scale(%lg,%lg,%lg), skew(%lg,%lg,%lg), "
2130       "quaternion(%lg,%lg,%lg,%lg), perspective(%lg,%lg,%lg,%lg)",
2131       decomposition.translate_x, decomposition.translate_y,
2132       decomposition.translate_z, decomposition.scale_x, decomposition.scale_y,
2133       decomposition.scale_z, decomposition.skew_xy, decomposition.skew_xz,
2134       decomposition.skew_yz, decomposition.quaternion_x,
2135       decomposition.quaternion_y, decomposition.quaternion_z,
2136       decomposition.quaternion_w, decomposition.perspective_x,
2137       decomposition.perspective_y, decomposition.perspective_z,
2138       decomposition.perspective_w);
2139 }
2140 
operator <<(std::ostream & ostream,const TransformationMatrix & transform)2141 std::ostream& operator<<(std::ostream& ostream,
2142                          const TransformationMatrix& transform) {
2143   return ostream << transform.ToString();
2144 }
2145 
RoundCloseToZero(double number)2146 static double RoundCloseToZero(double number) {
2147   return std::abs(number) < 1e-7 ? 0 : number;
2148 }
2149 
TransformAsJSONArray(const TransformationMatrix & t)2150 std::unique_ptr<JSONArray> TransformAsJSONArray(const TransformationMatrix& t) {
2151   auto array = std::make_unique<JSONArray>();
2152   {
2153     auto row = std::make_unique<JSONArray>();
2154     row->PushDouble(RoundCloseToZero(t.M11()));
2155     row->PushDouble(RoundCloseToZero(t.M12()));
2156     row->PushDouble(RoundCloseToZero(t.M13()));
2157     row->PushDouble(RoundCloseToZero(t.M14()));
2158     array->PushArray(std::move(row));
2159   }
2160   {
2161     auto row = std::make_unique<JSONArray>();
2162     row->PushDouble(RoundCloseToZero(t.M21()));
2163     row->PushDouble(RoundCloseToZero(t.M22()));
2164     row->PushDouble(RoundCloseToZero(t.M23()));
2165     row->PushDouble(RoundCloseToZero(t.M24()));
2166     array->PushArray(std::move(row));
2167   }
2168   {
2169     auto row = std::make_unique<JSONArray>();
2170     row->PushDouble(RoundCloseToZero(t.M31()));
2171     row->PushDouble(RoundCloseToZero(t.M32()));
2172     row->PushDouble(RoundCloseToZero(t.M33()));
2173     row->PushDouble(RoundCloseToZero(t.M34()));
2174     array->PushArray(std::move(row));
2175   }
2176   {
2177     auto row = std::make_unique<JSONArray>();
2178     row->PushDouble(RoundCloseToZero(t.M41()));
2179     row->PushDouble(RoundCloseToZero(t.M42()));
2180     row->PushDouble(RoundCloseToZero(t.M43()));
2181     row->PushDouble(RoundCloseToZero(t.M44()));
2182     array->PushArray(std::move(row));
2183   }
2184   return array;
2185 }
2186 
2187 }  // namespace blink
2188