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