Index: polymer_0.5.0/bower_components/web-animations-js/src/matrix-decomposition.js |
diff --git a/polymer_0.5.0/bower_components/web-animations-js/src/matrix-decomposition.js b/polymer_0.5.0/bower_components/web-animations-js/src/matrix-decomposition.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6617c8e3b790265f6991f71ecf8587d5d138788c |
--- /dev/null |
+++ b/polymer_0.5.0/bower_components/web-animations-js/src/matrix-decomposition.js |
@@ -0,0 +1,452 @@ |
+// Copyright 2014 Google Inc. All rights reserved. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
+ |
+(function(scope, testing) { |
+ var decomposeMatrix = (function() { |
+ function determinant(m) { |
+ return m[0][0] * m[1][1] * m[2][2] + |
+ m[1][0] * m[2][1] * m[0][2] + |
+ m[2][0] * m[0][1] * m[1][2] - |
+ m[0][2] * m[1][1] * m[2][0] - |
+ m[1][2] * m[2][1] * m[0][0] - |
+ m[2][2] * m[0][1] * m[1][0]; |
+ } |
+ |
+ // from Wikipedia: |
+ // |
+ // [A B]^-1 = [A^-1 + A^-1B(D - CA^-1B)^-1CA^-1 -A^-1B(D - CA^-1B)^-1] |
+ // [C D] [-(D - CA^-1B)^-1CA^-1 (D - CA^-1B)^-1 ] |
+ // |
+ // Therefore |
+ // |
+ // [A [0]]^-1 = [A^-1 [0]] |
+ // [C 1 ] [ -CA^-1 1 ] |
+ function inverse(m) { |
+ var iDet = 1 / determinant(m); |
+ var a = m[0][0], b = m[0][1], c = m[0][2]; |
+ var d = m[1][0], e = m[1][1], f = m[1][2]; |
+ var g = m[2][0], h = m[2][1], k = m[2][2]; |
+ var Ainv = [ |
+ [(e * k - f * h) * iDet, (c * h - b * k) * iDet, |
+ (b * f - c * e) * iDet, 0], |
+ [(f * g - d * k) * iDet, (a * k - c * g) * iDet, |
+ (c * d - a * f) * iDet, 0], |
+ [(d * h - e * g) * iDet, (g * b - a * h) * iDet, |
+ (a * e - b * d) * iDet, 0] |
+ ]; |
+ var lastRow = []; |
+ for (var i = 0; i < 3; i++) { |
+ var val = 0; |
+ for (var j = 0; j < 3; j++) { |
+ val += m[3][j] * Ainv[j][i]; |
+ } |
+ lastRow.push(val); |
+ } |
+ lastRow.push(1); |
+ Ainv.push(lastRow); |
+ return Ainv; |
+ } |
+ |
+ function transposeMatrix4(m) { |
+ return [[m[0][0], m[1][0], m[2][0], m[3][0]], |
+ [m[0][1], m[1][1], m[2][1], m[3][1]], |
+ [m[0][2], m[1][2], m[2][2], m[3][2]], |
+ [m[0][3], m[1][3], m[2][3], m[3][3]]]; |
+ } |
+ |
+ function multVecMatrix(v, m) { |
+ var result = []; |
+ for (var i = 0; i < 4; i++) { |
+ var val = 0; |
+ for (var j = 0; j < 4; j++) { |
+ val += v[j] * m[j][i]; |
+ } |
+ result.push(val); |
+ } |
+ return result; |
+ } |
+ |
+ function normalize(v) { |
+ var len = length(v); |
+ return [v[0] / len, v[1] / len, v[2] / len]; |
+ } |
+ |
+ function length(v) { |
+ return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); |
+ } |
+ |
+ function combine(v1, v2, v1s, v2s) { |
+ return [v1s * v1[0] + v2s * v2[0], v1s * v1[1] + v2s * v2[1], |
+ v1s * v1[2] + v2s * v2[2]]; |
+ } |
+ |
+ function cross(v1, v2) { |
+ return [v1[1] * v2[2] - v1[2] * v2[1], |
+ v1[2] * v2[0] - v1[0] * v2[2], |
+ v1[0] * v2[1] - v1[1] * v2[0]]; |
+ } |
+ |
+ // TODO: Implement 2D matrix decomposition. |
+ // http://dev.w3.org/csswg/css-transforms/#decomposing-a-2d-matrix |
+ function decomposeMatrix(matrix) { |
+ var m3d = [ |
+ matrix.slice(0, 4), |
+ matrix.slice(4, 8), |
+ matrix.slice(8, 12), |
+ matrix.slice(12, 16) |
+ ]; |
+ |
+ // skip normalization step as m3d[3][3] should always be 1 |
+ if (m3d[3][3] !== 1) { |
+ return null; |
+ } |
+ |
+ var perspectiveMatrix = []; |
+ for (var i = 0; i < 4; i++) { |
+ perspectiveMatrix.push(m3d[i].slice()); |
+ } |
+ |
+ for (var i = 0; i < 3; i++) { |
+ perspectiveMatrix[i][3] = 0; |
+ } |
+ |
+ if (determinant(perspectiveMatrix) === 0) { |
+ return false; |
+ } |
+ |
+ var rhs = []; |
+ |
+ var perspective; |
+ if (m3d[0][3] || m3d[1][3] || m3d[2][3]) { |
+ rhs.push(m3d[0][3]); |
+ rhs.push(m3d[1][3]); |
+ rhs.push(m3d[2][3]); |
+ rhs.push(m3d[3][3]); |
+ |
+ var inversePerspectiveMatrix = inverse(perspectiveMatrix); |
+ var transposedInversePerspectiveMatrix = |
+ transposeMatrix4(inversePerspectiveMatrix); |
+ perspective = multVecMatrix(rhs, transposedInversePerspectiveMatrix); |
+ } else { |
+ perspective = [0, 0, 0, 1]; |
+ } |
+ |
+ var translate = m3d[3].slice(0, 3); |
+ |
+ var row = []; |
+ row.push(m3d[0].slice(0, 3)); |
+ var scale = []; |
+ scale.push(length(row[0])); |
+ row[0] = normalize(row[0]); |
+ |
+ var skew = []; |
+ row.push(m3d[1].slice(0, 3)); |
+ skew.push(dot(row[0], row[1])); |
+ row[1] = combine(row[1], row[0], 1.0, -skew[0]); |
+ |
+ scale.push(length(row[1])); |
+ row[1] = normalize(row[1]); |
+ skew[0] /= scale[1]; |
+ |
+ row.push(m3d[2].slice(0, 3)); |
+ skew.push(dot(row[0], row[2])); |
+ row[2] = combine(row[2], row[0], 1.0, -skew[1]); |
+ skew.push(dot(row[1], row[2])); |
+ row[2] = combine(row[2], row[1], 1.0, -skew[2]); |
+ |
+ scale.push(length(row[2])); |
+ row[2] = normalize(row[2]); |
+ skew[1] /= scale[2]; |
+ skew[2] /= scale[2]; |
+ |
+ var pdum3 = cross(row[1], row[2]); |
+ if (dot(row[0], pdum3) < 0) { |
+ for (var i = 0; i < 3; i++) { |
+ scale[i] *= -1; |
+ row[i][0] *= -1; |
+ row[i][1] *= -1; |
+ row[i][2] *= -1; |
+ } |
+ } |
+ |
+ var t = row[0][0] + row[1][1] + row[2][2] + 1; |
+ var s; |
+ var quaternion; |
+ |
+ if (t > 1e-4) { |
+ s = 0.5 / Math.sqrt(t); |
+ quaternion = [ |
+ (row[2][1] - row[1][2]) * s, |
+ (row[0][2] - row[2][0]) * s, |
+ (row[1][0] - row[0][1]) * s, |
+ 0.25 / s |
+ ]; |
+ } else if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) { |
+ s = Math.sqrt(1 + row[0][0] - row[1][1] - row[2][2]) * 2.0; |
+ quaternion = [ |
+ 0.25 * s, |
+ (row[0][1] + row[1][0]) / s, |
+ (row[0][2] + row[2][0]) / s, |
+ (row[2][1] - row[1][2]) / s |
+ ]; |
+ } else if (row[1][1] > row[2][2]) { |
+ s = Math.sqrt(1.0 + row[1][1] - row[0][0] - row[2][2]) * 2.0; |
+ quaternion = [ |
+ (row[0][1] + row[1][0]) / s, |
+ 0.25 * s, |
+ (row[1][2] + row[2][1]) / s, |
+ (row[0][2] - row[2][0]) / s |
+ ]; |
+ } else { |
+ s = Math.sqrt(1.0 + row[2][2] - row[0][0] - row[1][1]) * 2.0; |
+ quaternion = [ |
+ (row[0][2] + row[2][0]) / s, |
+ (row[1][2] + row[2][1]) / s, |
+ 0.25 * s, |
+ (row[1][0] - row[0][1]) / s |
+ ]; |
+ } |
+ |
+ return [translate, scale, skew, quaternion, perspective]; |
+ } |
+ return decomposeMatrix; |
+ })(); |
+ |
+ function dot(v1, v2) { |
+ var result = 0; |
+ for (var i = 0; i < v1.length; i++) { |
+ result += v1[i] * v2[i]; |
+ } |
+ return result; |
+ } |
+ |
+ function multiplyMatrices(a, b) { |
+ return [ |
+ a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3], |
+ a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3], |
+ a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3], |
+ a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3], |
+ |
+ a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7], |
+ a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7], |
+ a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7], |
+ a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7], |
+ |
+ a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11], |
+ a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11], |
+ a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11], |
+ a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11], |
+ |
+ a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15], |
+ a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15], |
+ a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15], |
+ a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15] |
+ ]; |
+ } |
+ |
+ // TODO: This can probably be made smaller. |
+ function convertItemToMatrix(item) { |
+ switch (item.t) { |
+ // TODO: Handle units other than rads and degs. |
+ case 'rotatex': |
+ var rads = item.d[0].rad || 0; |
+ var degs = item.d[0].deg || 0; |
+ var angle = (degs * Math.PI / 180) + rads; |
+ return [1, 0, 0, 0, |
+ 0, Math.cos(angle), Math.sin(angle), 0, |
+ 0, -Math.sin(angle), Math.cos(angle), 0, |
+ 0, 0, 0, 1]; |
+ case 'rotatey': |
+ var rads = item.d[0].rad || 0; |
+ var degs = item.d[0].deg || 0; |
+ var angle = (degs * Math.PI / 180) + rads; |
+ return [Math.cos(angle), 0, -Math.sin(angle), 0, |
+ 0, 1, 0, 0, |
+ Math.sin(angle), 0, Math.cos(angle), 0, |
+ 0, 0, 0, 1]; |
+ case 'rotate': |
+ case 'rotatez': |
+ var rads = item.d[0].rad || 0; |
+ var degs = item.d[0].deg || 0; |
+ var angle = (degs * Math.PI / 180) + rads; |
+ return [Math.cos(angle), Math.sin(angle), 0, 0, |
+ -Math.sin(angle), Math.cos(angle), 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, 0, 1]; |
+ case 'rotate3d': |
+ var x = item.d[0]; |
+ var y = item.d[1]; |
+ var z = item.d[2]; |
+ var rads = item.d[3].rad || 0; |
+ var degs = item.d[3].deg || 0; |
+ var angle = (degs * Math.PI / 180) + rads; |
+ |
+ var sqrLength = x * x + y * y + z * z; |
+ if (sqrLength === 0) { |
+ x = 1; |
+ y = 0; |
+ z = 0; |
+ } else if (sqrLength !== 1) { |
+ var length = Math.sqrt(sqrLength); |
+ x /= length; |
+ y /= length; |
+ z /= length; |
+ } |
+ |
+ var s = Math.sin(angle / 2); |
+ var sc = s * Math.cos(angle / 2); |
+ var sq = s * s; |
+ return [ |
+ 1 - 2 * (y * y + z * z) * sq, |
+ 2 * (x * y * sq + z * sc), |
+ 2 * (x * z * sq - y * sc), |
+ 0, |
+ |
+ 2 * (x * y * sq - z * sc), |
+ 1 - 2 * (x * x + z * z) * sq, |
+ 2 * (y * z * sq + x * sc), |
+ 0, |
+ |
+ 2 * (x * z * sq + y * sc), |
+ 2 * (y * z * sq - x * sc), |
+ 1 - 2 * (x * x + y * y) * sq, |
+ 0, |
+ |
+ 0, 0, 0, 1 |
+ ]; |
+ case 'scale': |
+ return [item.d[0], 0, 0, 0, |
+ 0, item.d[1], 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, 0, 1]; |
+ case 'scalex': |
+ return [item.d[0], 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, 0, 1]; |
+ case 'scaley': |
+ return [1, 0, 0, 0, |
+ 0, item.d[0], 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, 0, 1]; |
+ case 'scalez': |
+ return [1, 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, item.d[0], 0, |
+ 0, 0, 0, 1]; |
+ case 'scale3d': |
+ return [item.d[0], 0, 0, 0, |
+ 0, item.d[1], 0, 0, |
+ 0, 0, item.d[2], 0, |
+ 0, 0, 0, 1]; |
+ // FIXME: Skew behaves differently in Blink, FireFox and here. Need to work out why. |
+ case 'skew': |
+ var xDegs = item.d[0].deg || 0; |
+ var xRads = item.d[0].rad || 0; |
+ var yDegs = item.d[1].deg || 0; |
+ var yRads = item.d[1].rad || 0; |
+ var xAngle = (xDegs * Math.PI / 180) + xRads; |
+ var yAngle = (yDegs * Math.PI / 180) + yRads; |
+ return [1, Math.tan(yAngle), 0, 0, |
+ Math.tan(xAngle), 1, 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, 0, 1]; |
+ case 'skewx': |
+ var rads = item.d[0].rad || 0; |
+ var degs = item.d[0].deg || 0; |
+ var angle = (degs * Math.PI / 180) + rads; |
+ return [1, 0, 0, 0, |
+ Math.tan(angle), 1, 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, 0, 1]; |
+ case 'skewy': |
+ var rads = item.d[0].rad || 0; |
+ var degs = item.d[0].deg || 0; |
+ var angle = (degs * Math.PI / 180) + rads; |
+ return [1, Math.tan(angle), 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, 0, 1]; |
+ // TODO: Work out what to do with non-px values. |
+ case 'translate': |
+ var x = item.d[0].px || 0; |
+ var y = item.d[1].px || 0; |
+ return [1, 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, 0, |
+ x, y, 0, 1]; |
+ case 'translatex': |
+ var x = item.d[0].px || 0; |
+ return [1, 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, 0, |
+ x, 0, 0, 1]; |
+ case 'translatey': |
+ var y = item.d[0].px || 0; |
+ return [1, 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, 0, |
+ 0, y, 0, 1]; |
+ case 'translatez': |
+ var z = item.d[0].px || 0; |
+ return [1, 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, z, 1]; |
+ case 'translate3d': |
+ var x = item.d[0].px || 0; |
+ var y = item.d[1].px || 0; |
+ var z = item.d[2].px || 0; |
+ return [1, 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, 0, |
+ x, y, z, 1]; |
+ case 'perspective': |
+ var p = item.d[0].px ? (-1 / item.d[0].px) : 0; |
+ return [ |
+ 1, 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, p, |
+ 0, 0, 0, 1]; |
+ case 'matrix': |
+ return [item.d[0], item.d[1], 0, 0, |
+ item.d[2], item.d[3], 0, 0, |
+ 0, 0, 1, 0, |
+ item.d[4], item.d[5], 0, 1]; |
+ case 'matrix3d': |
+ return item.d; |
+ default: |
+ WEB_ANIMATIONS_TESTING && console.assert(false, 'Transform item type ' + item.t + |
+ ' conversion to matrix not yet implemented.'); |
+ } |
+ } |
+ |
+ function convertToMatrix(transformList) { |
+ if (transformList.length === 0) { |
+ return [1, 0, 0, 0, |
+ 0, 1, 0, 0, |
+ 0, 0, 1, 0, |
+ 0, 0, 0, 1]; |
+ } |
+ return transformList.map(convertItemToMatrix).reduce(multiplyMatrices); |
+ } |
+ |
+ function makeMatrixDecomposition(transformList) { |
+ return [decomposeMatrix(convertToMatrix(transformList))]; |
+ } |
+ |
+ scope.dot = dot; |
+ scope.makeMatrixDecomposition = makeMatrixDecomposition; |
+ |
+})(webAnimationsMinifill, webAnimationsTesting); |