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