Changeset 156553 in webkit
- Timestamp:
- Sep 27, 2013 10:26:05 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r156551 r156553 1 2013-09-26 Dean Jackson <dino@apple.com> 2 3 Provide 2D Matrix decomposition for animation 4 https://bugs.webkit.org/show_bug.cgi?id=112824 5 <rdar://problem/15091882> 6 7 Reviewed by Eric Carlson (and Ian Henderson offline). 8 9 This test was only exercising the fact that our 10 software decomposition did not match our hardware 11 decomposition (although that required visual inspection). 12 Now that our 2d decomposition is correct, update the 13 test and its expected result. 14 15 * animations/transform-non-accelerated-expected.txt: 16 * animations/transform-non-accelerated.html: 17 1 18 2013-09-27 Mario Sanchez Prada <mario.prada@samsung.com> 2 19 -
trunk/LayoutTests/animations/transform-non-accelerated-expected.txt
r156506 r156553 1 1 During the animation, the box should flip in the horizontal axis. It should not disappear into a single point (i.e. the visual width should not change). 2 2 3 PASS - "webkitTransform" property for "box" element at 0.5s saw something close to: 0,0,0,0,0,03 PASS - "webkitTransform" property for "box" element at 0.5s saw something close to: 1,0,0,0,0,0 4 4 -
trunk/LayoutTests/animations/transform-non-accelerated.html
r156506 r156553 30 30 const expectedValues = [ 31 31 // [animation-name, time, element-id, property, expected-value, tolerance] 32 ["flip", 0.5, "box", "webkitTransform", [ 0, 0, 0, 0, 0, 0], 0.3],32 ["flip", 0.5, "box", "webkitTransform", [1, 0, 0, 0, 0, 0], 0.3], 33 33 ]; 34 34 -
trunk/Source/WebCore/ChangeLog
r156550 r156553 1 2013-09-26 Dean Jackson <dino@apple.com> 2 3 Provide 2D Matrix decomposition for animation 4 https://bugs.webkit.org/show_bug.cgi?id=112824 5 <rdar://problem/15091882> 6 7 Reviewed by Eric Carlson (and Ian Henderson offline). 8 9 Implement a new 2d matrix blend, which is triggered 10 when animating between two affine 3d matrices. This 11 is intended to be the official algorithm that gets 12 put into the W3C Transforms specification. 13 14 The old code is renamed with a 4 prefix (indicating 15 it is a blend between 3d matrices using quaternions), 16 and new methods and structures for 2d blending were added. 17 18 I also took the opportunity to clean up a lot of 19 bad WebKit style. 20 21 * platform/graphics/ca/GraphicsLayerCA.cpp: 22 (WebCore::maxScaleFromTransform): Use 3d decomposition. 23 * platform/graphics/transforms/PerspectiveTransformOperation.cpp: 24 (WebCore::PerspectiveTransformOperation::blend): Ditto. 25 * platform/graphics/transforms/RotateTransformOperation.cpp: 26 (WebCore::RotateTransformOperation::blend): Ditto. 27 28 * platform/graphics/transforms/TransformationMatrix.cpp: 29 (WebCore::decompose2): New method to decompose an affine 3d matrix 30 into X/Y scale + translate, a rotation angle, plus some extracted 31 a,b,c,d fields from the affine section. 32 (WebCore::decompose4): New name for the old function. 33 (WebCore::TransformationMatrix::blend2): Perform linear interpolation 34 between two 2d decompositions. 35 (WebCore::TransformationMatrix::blend4): New name for the old function. 36 (WebCore::TransformationMatrix::blend): Call blend2 or blend4 depending 37 on the type of matrix. 38 (WebCore::TransformationMatrix::decompose2): Calls into the decompose2 39 method above. 40 (WebCore::TransformationMatrix::decompose4): New name. 41 (WebCore::TransformationMatrix::recompose2): Recomposes a 3d matrix from 42 a 2d decomposition. 43 (WebCore::TransformationMatrix::recompose4): New name. 44 * platform/graphics/transforms/TransformationMatrix.h: All the changes 45 for the new methods above. 46 1 47 2013-09-26 Darin Adler <darin@apple.com> 2 48 -
trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
r156301 r156553 257 257 return 1; 258 258 259 TransformationMatrix::Decomposed Type decomposeData;260 t.decompose (decomposeData);259 TransformationMatrix::Decomposed4Type decomposeData; 260 t.decompose4(decomposeData); 261 261 return std::max(fabsf(decomposeData.scaleX), fabsf(decomposeData.scaleY)); 262 262 } -
trunk/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp
r111126 r156553 54 54 toT.applyPerspective(floatValueForLength(toP, 1)); 55 55 toT.blend(fromT, progress); 56 TransformationMatrix::Decomposed Type decomp;57 toT.decompose (decomp);56 TransformationMatrix::Decomposed4Type decomp; 57 toT.decompose4(decomp); 58 58 59 59 if (decomp.perspectiveZ) { -
trunk/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.cpp
r136964 r156553 71 71 72 72 // Extract the result as a quaternion 73 TransformationMatrix::Decomposed Type decomp;74 toT.decompose (decomp);73 TransformationMatrix::Decomposed4Type decomp; 74 toT.decompose4(decomp); 75 75 76 76 // Convert that to Axis/Angle form -
trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
r142810 r156553 1 1 /* 2 * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.2 * Copyright (C) 2005, 2006, 2013 Apple Computer, Inc. All rights reserved. 3 3 * Copyright (C) 2009 Torch Mobile, Inc. 4 4 * … … 22 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 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. 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 25 */ 26 26 … … 55 55 // Adapted from Matrix Inversion by Richard Carling, Graphics Gems <http://tog.acm.org/GraphicsGems/index.html>. 56 56 57 // EULA: The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code 58 // as your own and resell it. Using the code is permitted in any program, product, or library, non-commercial 59 // or commercial. Giving credit is not required, though is a nice gesture. The code comes as-is, and if there 60 // are any flaws or problems with any Gems code, nobody involved with Gems - authors, editors, publishers, or 61 // webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes 57 // EULA: The Graphics Gems code is copyright-protected. In other words, you cannot claim the text of the code 58 // as your own and resell it. Using the code is permitted in any program, product, or library, non-commercial 59 // or commercial. Giving credit is not required, though is a nice gesture. The code comes as-is, and if there 60 // are any flaws or problems with any Gems code, nobody involved with Gems - authors, editors, publishers, or 61 // webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes 62 62 // with no guarantee. 63 63 64 64 // A clarification about the storage of matrix elements 65 65 // 66 // This class uses a 2 dimensional array internally to store the elements of the matrix. The first index into66 // This class uses a 2 dimensional array internally to store the elements of the matrix. The first index into 67 67 // the array refers to the column that the element lies in; the second index refers to the row. 68 68 // … … 80 80 81 81 // inverse(original_matrix, inverse_matrix) 82 // 82 // 83 83 // calculate the inverse of a 4x4 matrix 84 // 85 // -1 84 // 85 // -1 86 86 // A = ___1__ adjoint A 87 87 // det A 88 88 89 89 // double = determinant2x2(double a, double b, double c, double d) 90 // 90 // 91 91 // calculate the determinant of a 2x2 matrix. 92 92 … … 97 97 98 98 // double = determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3) 99 // 99 // 100 100 // Calculate the determinant of a 3x3 matrix 101 101 // in the form 102 // 102 // 103 103 // | a1, b1, c1 | 104 104 // | a2, b2, c2 | … … 113 113 114 114 // double = determinant4x4(matrix) 115 // 115 // 116 116 // calculate the determinant of a 4x4 matrix. 117 117 … … 122 122 123 123 double a1 = m[0][0]; 124 double b1 = m[0][1]; 124 double b1 = m[0][1]; 125 125 double c1 = m[0][2]; 126 126 double d1 = m[0][3]; 127 127 128 128 double a2 = m[1][0]; 129 double b2 = m[1][1]; 129 double b2 = m[1][1]; 130 130 double c2 = m[1][2]; 131 131 double d2 = m[1][3]; 132 132 133 double a3 = m[2][0]; 133 double a3 = m[2][0]; 134 134 double b3 = m[2][1]; 135 135 double c3 = m[2][2]; … … 137 137 138 138 double a4 = m[3][0]; 139 double b4 = m[3][1]; 139 double b4 = m[3][1]; 140 140 double c4 = m[3][2]; 141 141 double d4 = m[3][3]; … … 155 155 // 156 156 // deleting the ith row and jth column from A. 157 // 157 // 158 158 // i+j 159 159 // Let b = (-1) a 160 160 // ij ji 161 // 161 // 162 162 // The matrix B = (b ) is the adjoint of A 163 163 // ij … … 168 168 // selecting correct values 169 169 double a1 = matrix[0][0]; 170 double b1 = matrix[0][1]; 170 double b1 = matrix[0][1]; 171 171 double c1 = matrix[0][2]; 172 172 double d1 = matrix[0][3]; 173 173 174 174 double a2 = matrix[1][0]; 175 double b2 = matrix[1][1]; 175 double b2 = matrix[1][1]; 176 176 double c2 = matrix[1][2]; 177 177 double d2 = matrix[1][3]; … … 183 183 184 184 double a4 = matrix[3][0]; 185 double b4 = matrix[3][1]; 185 double b4 = matrix[3][1]; 186 186 double c4 = matrix[3][2]; 187 187 double d4 = matrix[3][3]; … … 192 192 result[2][0] = determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4); 193 193 result[3][0] = - determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4); 194 194 195 195 result[0][1] = - determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4); 196 196 result[1][1] = determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4); 197 197 result[2][1] = - determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4); 198 198 result[3][1] = determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4); 199 199 200 200 result[0][2] = determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4); 201 201 result[1][2] = - determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4); 202 202 result[2][2] = determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4); 203 203 result[3][2] = - determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4); 204 204 205 205 result[0][3] = - determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3); 206 206 result[1][3] = determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3); … … 216 216 217 217 // Calculate the 4x4 determinant 218 // If the determinant is zero, 218 // If the determinant is zero, 219 219 // then the inverse matrix is not unique. 220 220 double det = determinant4x4(matrix); … … 263 263 } 264 264 265 static void v3Scale(Vector3 v, double desiredLength) 265 static void v3Scale(Vector3 v, double desiredLength) 266 266 { 267 267 double len = v3Length(v); … … 274 274 } 275 275 276 static double v3Dot(const Vector3 a, const Vector3 b) 276 static double v3Dot(const Vector3 a, const Vector3 b) 277 277 { 278 278 return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]); … … 296 296 } 297 297 298 static bool decompose(const TransformationMatrix::Matrix4& mat, TransformationMatrix::DecomposedType& result) 298 static bool decompose2(const TransformationMatrix::Matrix4& matrix, TransformationMatrix::Decomposed2Type& result) 299 { 300 double row0x = matrix[0][0]; 301 double row0y = matrix[0][1]; 302 double row1x = matrix[1][0]; 303 double row1y = matrix[1][1]; 304 result.translateX = matrix[3][0]; 305 result.translateY = matrix[3][1]; 306 307 // Compute scaling factors. 308 result.scaleX = sqrt(row0x * row0x + row0y * row0y); 309 result.scaleY = sqrt(row1x * row1x + row1y * row1y); 310 311 // If determinant is negative, one axis was flipped. 312 double determinant = row0x * row1y - row0y * row1x; 313 if (determinant < 0) { 314 // Flip axis with minimum unit vector dot product. 315 if (row0x < row1y) 316 result.scaleX = -result.scaleX; 317 else 318 result.scaleY = -result.scaleY; 319 } 320 321 // Renormalize matrix to remove scale. 322 if (result.scaleX) { 323 row0x *= 1 / result.scaleX; 324 row0y *= 1 / result.scaleX; 325 } 326 if (result.scaleY) { 327 row1x *= 1 / result.scaleY; 328 row1y *= 1 / result.scaleY; 329 } 330 331 // Compute rotation and renormalize matrix. 332 result.angle = atan2(row0y, row0x); 333 334 if (result.angle) { 335 // Rotate(-angle) = [cos(angle), sin(angle), -sin(angle), cos(angle)] 336 // = [row0x, -row0y, row0y, row0x] 337 // Thanks to the normalization above. 338 double sn = -row0y; 339 double cs = row0x; 340 double m11 = row0x, m12 = row0y; 341 double m21 = row1x, m22 = row1y; 342 343 row0x = cs * m11 + sn * m21; 344 row0y = cs * m12 + sn * m22; 345 row1x = -sn * m11 + cs * m21; 346 row1y = -sn * m12 + cs * m22; 347 } 348 349 result.m11 = row0x; 350 result.m12 = row0y; 351 result.m21 = row1x; 352 result.m22 = row1y; 353 354 // Convert into degrees because our rotation functions expect it. 355 result.angle = rad2deg(result.angle); 356 357 return true; 358 } 359 360 static bool decompose4(const TransformationMatrix::Matrix4& mat, TransformationMatrix::Decomposed4Type& result) 299 361 { 300 362 TransformationMatrix::Matrix4 localMatrix; … … 321 383 return false; 322 384 323 // First, isolate perspective. 385 // First, isolate perspective. This is the messiest. 324 386 if (localMatrix[0][3] != 0 || localMatrix[1][3] != 0 || localMatrix[2][3] != 0) { 325 387 // rightHandSide is the right hand side of the equation. … … 331 393 332 394 // Solve the equation by inverting perspectiveMatrix and multiplying 333 // rightHandSide by the inverse. 395 // rightHandSide by the inverse. (This is the easiest way, not 334 396 // necessarily the best.) 335 397 TransformationMatrix::Matrix4 inversePerspectiveMatrix, transposedInversePerspectiveMatrix; … … 339 401 Vector4 perspectivePoint; 340 402 v4MulPointByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspectivePoint); 341 403 342 404 result.perspectiveX = perspectivePoint[0]; 343 405 result.perspectiveY = perspectivePoint[1]; 344 406 result.perspectiveZ = perspectivePoint[2]; 345 407 result.perspectiveW = perspectivePoint[3]; 346 408 347 409 // Clear the perspective partition 348 410 localMatrix[0][3] = localMatrix[1][3] = localMatrix[2][3] = 0; … … 353 415 result.perspectiveW = 1; 354 416 } 355 417 356 418 // Next take care of translation (easy). 357 419 result.translateX = localMatrix[3][0]; … … 396 458 result.skewXZ /= result.scaleZ; 397 459 result.skewYZ /= result.scaleZ; 398 460 399 461 // At this point, the matrix (in rows[]) is orthonormal. 400 // Check for a coordinate system flip. 462 // Check for a coordinate system flip. If the determinant 401 463 // is -1, then negate the matrix and the scaling factors. 402 464 v3Cross(row[1], row[2], pdum3); … … 413 475 } 414 476 } 415 477 416 478 // Now, get the rotations out, as described in the gem. 417 479 418 480 // FIXME - Add the ability to return either quaternions (which are 419 481 // easier to recompose with) or Euler angles (rx, ry, rz), which … … 430 492 // ret.rotateZ = 0; 431 493 // } 432 494 433 495 double s, t, x, y, z, w; 434 496 … … 441 503 y = (row[0][2] - row[2][0]) * s; 442 504 z = (row[1][0] - row[0][1]) * s; 443 } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) { 444 s = sqrt (1.0 + row[0][0] - row[1][1] - row[2][2]) * 2.0; // S=4*qx505 } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) { 506 s = sqrt(1.0 + row[0][0] - row[1][1] - row[2][2]) * 2.0; // S = 4 * qx. 445 507 x = 0.25 * s; 446 y = (row[0][1] + row[1][0]) / s; 447 z = (row[0][2] + row[2][0]) / s; 508 y = (row[0][1] + row[1][0]) / s; 509 z = (row[0][2] + row[2][0]) / s; 448 510 w = (row[2][1] - row[1][2]) / s; 449 } else if (row[1][1] > row[2][2]) { 450 s = sqrt (1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; // S=4*qy451 x = (row[0][1] + row[1][0]) / s; 511 } else if (row[1][1] > row[2][2]) { 512 s = sqrt(1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; // S = 4 * qy. 513 x = (row[0][1] + row[1][0]) / s; 452 514 y = 0.25 * s; 453 z = (row[1][2] + row[2][1]) / s; 515 z = (row[1][2] + row[2][1]) / s; 454 516 w = (row[0][2] - row[2][0]) / s; 455 } else { 456 s = sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; // S =4*qz517 } else { 518 s = sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; // S = 4 * qz. 457 519 x = (row[0][2] + row[2][0]) / s; 458 y = (row[1][2] + row[2][1]) / s; 520 y = (row[1][2] + row[2][1]) / s; 459 521 z = 0.25 * s; 460 522 w = (row[1][0] - row[0][1]) / s; … … 465 527 result.quaternionZ = z; 466 528 result.quaternionW = w; 467 529 468 530 return true; 469 531 } 470 532 471 533 // Perform a spherical linear interpolation between the two 472 // passed quaternions with 0 <= t <= 1 534 // passed quaternions with 0 <= t <= 1. 473 535 static void slerp(double qa[4], const double qb[4], double t) 474 536 { … … 552 614 // inverse transform to find the corresponding point in the source 553 615 // space. 554 // 616 // 555 617 // Given a plane with normal Pn, and a ray starting at point R0 and 556 618 // with direction defined by the vector Rd, we can find the 557 619 // intersection point as a distance d from R0 in units of Rd by: 558 // 620 // 559 621 // d = -dot (Pn', R0) / dot (Pn', Rd) 560 622 if (clamped) … … 566 628 return FloatPoint(); 567 629 } 568 630 569 631 double x = p.x(); 570 632 double y = p.y(); … … 609 671 if (clamped) 610 672 *clamped = clamped1 || clamped2 || clamped3 || clamped4; 611 673 612 674 // If all points on the quad had w < 0, then the entire quad would not be visible to the projected surface. 613 675 bool everythingWasClipped = clamped1 && clamped2 && clamped3 && clamped4; … … 716 778 m_matrix[0][2] *= sx; 717 779 m_matrix[0][3] *= sx; 718 780 719 781 m_matrix[1][0] *= sy; 720 782 m_matrix[1][1] *= sy; … … 727 789 { 728 790 scaleNonUniform(sx, sy); 729 791 730 792 m_matrix[2][0] *= sz; 731 793 m_matrix[2][1] *= sz; … … 740 802 double length = sqrt(x * x + y * y + z * z); 741 803 if (length == 0) { 742 // A direction vector that cannot be normalized, such as [0, 0, 0], will cause the rotation to not be applied. 804 // A direction vector that cannot be normalized, such as [0, 0, 0], will cause the rotation to not be applied. 743 805 return *this; 744 806 } else if (length != 1) { … … 753 815 double sinTheta = sin(angle); 754 816 double cosTheta = cos(angle); 755 817 756 818 TransformationMatrix mat; 757 819 … … 828 890 ry = deg2rad(ry); 829 891 rz = deg2rad(rz); 830 892 831 893 TransformationMatrix mat; 832 894 833 895 double sinTheta = sin(rz); 834 896 double cosTheta = cos(rz); 835 897 836 898 mat.m_matrix[0][0] = cosTheta; 837 899 mat.m_matrix[0][1] = sinTheta; … … 846 908 mat.m_matrix[3][0] = mat.m_matrix[3][1] = mat.m_matrix[3][2] = 0.0; 847 909 mat.m_matrix[3][3] = 1.0; 848 910 849 911 TransformationMatrix rmat(mat); 850 912 851 913 sinTheta = sin(ry); 852 914 cosTheta = cos(ry); 853 915 854 916 mat.m_matrix[0][0] = cosTheta; 855 917 mat.m_matrix[0][1] = 0.0; … … 869 931 sinTheta = sin(rx); 870 932 cosTheta = cos(rx); 871 933 872 934 mat.m_matrix[0][0] = 1.0; 873 935 mat.m_matrix[0][1] = 0.0; … … 944 1006 sx = deg2rad(sx); 945 1007 sy = deg2rad(sy); 946 1008 947 1009 TransformationMatrix mat; 948 1010 mat.m_matrix[0][1] = tan(sy); // note that the y shear goes in the first row … … 1243 1305 #else 1244 1306 Matrix4 tmp; 1245 1307 1246 1308 tmp[0][0] = (mat.m_matrix[0][0] * m_matrix[0][0] + mat.m_matrix[0][1] * m_matrix[1][0] 1247 1309 + mat.m_matrix[0][2] * m_matrix[2][0] + mat.m_matrix[0][3] * m_matrix[3][0]); … … 1279 1341 tmp[3][3] = (mat.m_matrix[3][0] * m_matrix[0][3] + mat.m_matrix[3][1] * m_matrix[1][3] 1280 1342 + mat.m_matrix[3][2] * m_matrix[2][3] + mat.m_matrix[3][3] * m_matrix[3][3]); 1281 1343 1282 1344 setMatrix(tmp); 1283 1345 #endif … … 1322 1384 } 1323 1385 1324 TransformationMatrix TransformationMatrix::inverse() const 1386 TransformationMatrix TransformationMatrix::inverse() const 1325 1387 { 1326 1388 if (isIdentityOrTranslation()) { … … 1328 1390 if (m_matrix[3][0] == 0 && m_matrix[3][1] == 0 && m_matrix[3][2] == 0) 1329 1391 return TransformationMatrix(); 1330 1392 1331 1393 // translation 1332 1394 return TransformationMatrix(1, 0, 0, 0, … … 1335 1397 -m_matrix[3][0], -m_matrix[3][1], -m_matrix[3][2], 1); 1336 1398 } 1337 1399 1338 1400 TransformationMatrix invMat; 1339 1401 bool inverted = WebCore::inverse(m_matrix, invMat.m_matrix); 1340 1402 if (!inverted) 1341 1403 return TransformationMatrix(); 1342 1404 1343 1405 return invMat; 1344 1406 } … … 1348 1410 m_matrix[0][2] = 0; 1349 1411 m_matrix[0][3] = 0; 1350 1412 1351 1413 m_matrix[1][2] = 0; 1352 1414 m_matrix[1][3] = 0; 1353 1415 1354 1416 m_matrix[2][0] = 0; 1355 1417 m_matrix[2][1] = 0; 1356 1418 m_matrix[2][2] = 1; 1357 1419 m_matrix[2][3] = 0; 1358 1420 1359 1421 m_matrix[3][2] = 0; 1360 1422 m_matrix[3][3] = 1; … … 1373 1435 } 1374 1436 1375 void TransformationMatrix::blend(const TransformationMatrix& from, double progress) 1376 { 1377 if (from.isIdentity() && isIdentity()) 1378 return; 1379 1380 // decompose 1381 DecomposedType fromDecomp; 1382 DecomposedType toDecomp; 1383 from.decompose(fromDecomp); 1384 decompose(toDecomp); 1385 1386 // interpolate 1437 void TransformationMatrix::blend2(const TransformationMatrix& from, double progress) 1438 { 1439 Decomposed2Type fromDecomp; 1440 Decomposed2Type toDecomp; 1441 from.decompose2(fromDecomp); 1442 decompose2(toDecomp); 1443 1444 // If x-axis of one is flipped, and y-axis of the other, convert to an unflipped rotation. 1445 if ((fromDecomp.scaleX < 0 && toDecomp.scaleY < 0) || (fromDecomp.scaleY < 0 && toDecomp.scaleX < 0)) { 1446 fromDecomp.scaleX = -fromDecomp.scaleX; 1447 fromDecomp.scaleY = -fromDecomp.scaleY; 1448 fromDecomp.angle += fromDecomp.angle < 0 ? 180 : -180; 1449 } 1450 1451 // Don't rotate the long way around. 1452 if (!fromDecomp.angle) 1453 fromDecomp.angle = 360; 1454 if (!toDecomp.angle) 1455 toDecomp.angle = 360; 1456 1457 if (fabs(fromDecomp.angle - toDecomp.angle) > 180) { 1458 if (fromDecomp.angle > toDecomp.angle) 1459 fromDecomp.angle -= 360; 1460 else 1461 toDecomp.angle -= 360; 1462 } 1463 1464 blendFloat(fromDecomp.m11, toDecomp.m11, progress); 1465 blendFloat(fromDecomp.m12, toDecomp.m12, progress); 1466 blendFloat(fromDecomp.m21, toDecomp.m21, progress); 1467 blendFloat(fromDecomp.m22, toDecomp.m22, progress); 1468 blendFloat(fromDecomp.translateX, toDecomp.translateX, progress); 1469 blendFloat(fromDecomp.translateY, toDecomp.translateY, progress); 1470 blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress); 1471 blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress); 1472 blendFloat(fromDecomp.angle, toDecomp.angle, progress); 1473 1474 recompose2(fromDecomp); 1475 } 1476 1477 void TransformationMatrix::blend4(const TransformationMatrix& from, double progress) 1478 { 1479 Decomposed4Type fromDecomp; 1480 Decomposed4Type toDecomp; 1481 from.decompose4(fromDecomp); 1482 decompose4(toDecomp); 1483 1387 1484 blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress); 1388 1485 blendFloat(fromDecomp.scaleY, toDecomp.scaleY, progress); … … 1398 1495 blendFloat(fromDecomp.perspectiveZ, toDecomp.perspectiveZ, progress); 1399 1496 blendFloat(fromDecomp.perspectiveW, toDecomp.perspectiveW, progress); 1400 1497 1401 1498 slerp(&fromDecomp.quaternionX, &toDecomp.quaternionX, progress); 1402 1403 // recompose 1404 recompose(fromDecomp); 1405 } 1406 1407 bool TransformationMatrix::decompose(DecomposedType& decomp) const 1499 1500 recompose4(fromDecomp); 1501 } 1502 1503 void TransformationMatrix::blend(const TransformationMatrix& from, double progress) 1504 { 1505 if (from.isIdentity() && isIdentity()) 1506 return; 1507 1508 if (from.isAffine() && isAffine()) 1509 blend2(from, progress); 1510 else 1511 blend4(from, progress); 1512 } 1513 1514 bool TransformationMatrix::decompose2(Decomposed2Type& decomp) const 1515 { 1516 if (isIdentity()) { 1517 memset(&decomp, 0, sizeof(decomp)); 1518 decomp.scaleX = 1; 1519 decomp.scaleY = 1; 1520 } 1521 1522 return WebCore::decompose2(m_matrix, decomp); 1523 } 1524 1525 bool TransformationMatrix::decompose4(Decomposed4Type& decomp) const 1408 1526 { 1409 1527 if (isIdentity()) { … … 1414 1532 decomp.scaleZ = 1; 1415 1533 } 1416 1417 if (!WebCore::decompose(m_matrix, decomp)) 1418 return false; 1419 return true; 1420 } 1421 1422 void TransformationMatrix::recompose(const DecomposedType& decomp) 1534 1535 return WebCore::decompose4(m_matrix, decomp); 1536 } 1537 1538 void TransformationMatrix::recompose2(const Decomposed2Type& decomp) 1423 1539 { 1424 1540 makeIdentity(); 1425 1426 // first apply perspective 1541 1542 m_matrix[0][0] = decomp.m11; 1543 m_matrix[0][1] = decomp.m12; 1544 m_matrix[1][0] = decomp.m21; 1545 m_matrix[1][1] = decomp.m22; 1546 1547 translate3d(decomp.translateX, decomp.translateY, 0); 1548 rotate(decomp.angle); 1549 scale3d(decomp.scaleX, decomp.scaleY, 1); 1550 } 1551 1552 void TransformationMatrix::recompose4(const Decomposed4Type& decomp) 1553 { 1554 makeIdentity(); 1555 1556 // First apply perspective. 1427 1557 m_matrix[0][3] = decomp.perspectiveX; 1428 1558 m_matrix[1][3] = decomp.perspectiveY; 1429 1559 m_matrix[2][3] = decomp.perspectiveZ; 1430 1560 m_matrix[3][3] = decomp.perspectiveW; 1431 1432 // now translate1561 1562 // Next, translate. 1433 1563 translate3d(decomp.translateX, decomp.translateY, decomp.translateZ); 1434 1435 // apply rotation1564 1565 // Apply rotation. 1436 1566 double xx = decomp.quaternionX * decomp.quaternionX; 1437 1567 double xy = decomp.quaternionX * decomp.quaternionY; … … 1443 1573 double zz = decomp.quaternionZ * decomp.quaternionZ; 1444 1574 double zw = decomp.quaternionZ * decomp.quaternionW; 1445 1446 // Construct a composite rotation matrix from the quaternion values 1447 TransformationMatrix rotationMatrix(1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0, 1575 1576 // Construct a composite rotation matrix from the quaternion values. 1577 TransformationMatrix rotationMatrix(1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw), 0, 1448 1578 2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw), 0, 1449 1579 2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy), 0, 1450 1580 0, 0, 0, 1); 1451 1581 1452 1582 multiply(rotationMatrix); 1453 1454 // now apply skew1583 1584 // Apply skew. 1455 1585 if (decomp.skewYZ) { 1456 1586 TransformationMatrix tmp; … … 1458 1588 multiply(tmp); 1459 1589 } 1460 1590 1461 1591 if (decomp.skewXZ) { 1462 1592 TransformationMatrix tmp; … … 1464 1594 multiply(tmp); 1465 1595 } 1466 1596 1467 1597 if (decomp.skewXY) { 1468 1598 TransformationMatrix tmp; … … 1470 1600 multiply(tmp); 1471 1601 } 1472 1473 // finally, apply scale1602 1603 // Finally, apply scale. 1474 1604 scale3d(decomp.scaleX, decomp.scaleY, decomp.scaleZ); 1475 1605 } -
trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
r155251 r156553 233 233 TransformationMatrix& scaleNonUniform(double sx, double sy); 234 234 TransformationMatrix& scale3d(double sx, double sy, double sz); 235 235 236 // Angle is in degrees. 236 237 TransformationMatrix& rotate(double d) { return rotate3d(0, 0, d); } 237 238 TransformationMatrix& rotateFromVector(double x, double y); … … 268 269 269 270 // decompose the matrix into its component parts 271 typedef struct { 272 double scaleX, scaleY; 273 double translateX, translateY; 274 double angle; 275 double m11, m12, m21, m22; 276 } Decomposed2Type; 277 270 278 typedef struct { 271 279 double scaleX, scaleY, scaleZ; … … 274 282 double translateX, translateY, translateZ; 275 283 double perspectiveX, perspectiveY, perspectiveZ, perspectiveW; 276 } DecomposedType; 277 278 bool decompose(DecomposedType& decomp) const; 279 void recompose(const DecomposedType& decomp); 280 284 } Decomposed4Type; 285 286 bool decompose2(Decomposed2Type&) const; 287 void recompose2(const Decomposed2Type&); 288 289 bool decompose4(Decomposed4Type&) const; 290 void recompose4(const Decomposed4Type&); 291 281 292 void blend(const TransformationMatrix& from, double progress); 293 void blend2(const TransformationMatrix& from, double progress); 294 void blend4(const TransformationMatrix& from, double progress); 282 295 283 296 bool isAffine() const
Note: See TracChangeset
for help on using the changeset viewer.