Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1086)

Side by Side Diff: third_party/WebKit/WebCore/platform/graphics/transforms/TransformationMatrix.cpp

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

Powered by Google App Engine
This is Rietveld 408576698