aboutsummaryrefslogtreecommitdiff
path: root/catapult/third_party/polymer/components/web-animations-js/src/transform-handler.js
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/third_party/polymer/components/web-animations-js/src/transform-handler.js')
-rw-r--r--catapult/third_party/polymer/components/web-animations-js/src/transform-handler.js275
1 files changed, 275 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/web-animations-js/src/transform-handler.js b/catapult/third_party/polymer/components/web-animations-js/src/transform-handler.js
new file mode 100644
index 00000000..c6b4d934
--- /dev/null
+++ b/catapult/third_party/polymer/components/web-animations-js/src/transform-handler.js
@@ -0,0 +1,275 @@
+// 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) {
+
+ // This returns a function for converting transform functions to equivalent
+ // primitive functions, which will take an array of values from the
+ // derivative type and fill in the blanks (underscores) with them.
+ var _ = null;
+ function cast(pattern) {
+ return function(contents) {
+ var i = 0;
+ return pattern.map(function(x) { return x === _ ? contents[i++] : x; });
+ }
+ }
+
+ function id(x) { return x; }
+
+ var Opx = {px: 0};
+ var Odeg = {deg: 0};
+
+ // type: [argTypes, convertTo3D, convertTo2D]
+ // In the argument types string, lowercase characters represent optional arguments
+ var transformFunctions = {
+ matrix: ['NNNNNN', [_, _, 0, 0, _, _, 0, 0, 0, 0, 1, 0, _, _, 0, 1], id],
+ matrix3d: ['NNNNNNNNNNNNNNNN', id],
+ rotate: ['A'],
+ rotatex: ['A'],
+ rotatey: ['A'],
+ rotatez: ['A'],
+ rotate3d: ['NNNA'],
+ perspective: ['L'],
+ scale: ['Nn', cast([_, _, 1]), id],
+ scalex: ['N', cast([_, 1, 1]), cast([_, 1])],
+ scaley: ['N', cast([1, _, 1]), cast([1, _])],
+ scalez: ['N', cast([1, 1, _])],
+ scale3d: ['NNN', id],
+ skew: ['Aa', null, id],
+ skewx: ['A', null, cast([_, Odeg])],
+ skewy: ['A', null, cast([Odeg, _])],
+ translate: ['Tt', cast([_, _, Opx]), id],
+ translatex: ['T', cast([_, Opx, Opx]), cast([_, Opx])],
+ translatey: ['T', cast([Opx, _, Opx]), cast([Opx, _])],
+ translatez: ['L', cast([Opx, Opx, _])],
+ translate3d: ['TTL', id],
+ };
+
+ function parseTransform(string) {
+ string = string.toLowerCase().trim();
+ if (string == 'none')
+ return [];
+ // FIXME: Using a RegExp means calcs won't work here
+ var transformRegExp = /\s*(\w+)\(([^)]*)\)/g;
+ var result = [];
+ var match;
+ var prevLastIndex = 0;
+ while (match = transformRegExp.exec(string)) {
+ if (match.index != prevLastIndex)
+ return;
+ prevLastIndex = match.index + match[0].length;
+ var functionName = match[1];
+ var functionData = transformFunctions[functionName];
+ if (!functionData)
+ return;
+ var args = match[2].split(',');
+ var argTypes = functionData[0];
+ if (argTypes.length < args.length)
+ return;
+
+ var parsedArgs = [];
+ for (var i = 0; i < argTypes.length; i++) {
+ var arg = args[i];
+ var type = argTypes[i];
+ var parsedArg;
+ if (!arg)
+ parsedArg = ({a: Odeg,
+ n: parsedArgs[0],
+ t: Opx})[type];
+ else
+ parsedArg = ({A: function(s) { return s.trim() == '0' ? Odeg : scope.parseAngle(s); },
+ N: scope.parseNumber,
+ T: scope.parseLengthOrPercent,
+ L: scope.parseLength})[type.toUpperCase()](arg);
+ if (parsedArg === undefined)
+ return;
+ parsedArgs.push(parsedArg);
+ }
+ result.push({t: functionName, d: parsedArgs});
+
+ if (transformRegExp.lastIndex == string.length)
+ return result;
+ }
+ };
+
+ function numberToLongString(x) {
+ return x.toFixed(6).replace('.000000', '');
+ }
+
+ function mergeMatrices(left, right) {
+ if (left.decompositionPair !== right) {
+ left.decompositionPair = right;
+ var leftArgs = scope.makeMatrixDecomposition(left);
+ }
+ if (right.decompositionPair !== left) {
+ right.decompositionPair = left;
+ var rightArgs = scope.makeMatrixDecomposition(right);
+ }
+ if (leftArgs[0] == null || rightArgs[0] == null)
+ return [[false], [true], function(x) { return x ? right[0].d : left[0].d; }];
+ leftArgs[0].push(0);
+ rightArgs[0].push(1);
+ return [
+ leftArgs,
+ rightArgs,
+ function(list) {
+ var quat = scope.quat(leftArgs[0][3], rightArgs[0][3], list[5]);
+ var mat = scope.composeMatrix(list[0], list[1], list[2], quat, list[4]);
+ var stringifiedArgs = mat.map(numberToLongString).join(',');
+ return stringifiedArgs;
+ }
+ ];
+ }
+
+ function typeTo2D(type) {
+ return type.replace(/[xy]/, '');
+ }
+
+ function typeTo3D(type) {
+ return type.replace(/(x|y|z|3d)?$/, '3d');
+ }
+
+ function mergeTransforms(left, right) {
+ var matrixModulesLoaded = scope.makeMatrixDecomposition && true;
+
+ var flipResults = false;
+ if (!left.length || !right.length) {
+ if (!left.length) {
+ flipResults = true;
+ left = right;
+ right = [];
+ }
+ for (var i = 0; i < left.length; i++) {
+ var type = left[i].t;
+ var args = left[i].d;
+ var defaultValue = type.substr(0, 5) == 'scale' ? 1 : 0;
+ right.push({t: type, d: args.map(function(arg) {
+ if (typeof arg == 'number')
+ return defaultValue;
+ var result = {};
+ for (var unit in arg)
+ result[unit] = defaultValue;
+ return result;
+ })});
+ }
+ }
+
+ var isMatrixOrPerspective = function(lt, rt) {
+ return ((lt == 'perspective') && (rt == 'perspective')) ||
+ ((lt == 'matrix' || lt == 'matrix3d') && (rt == 'matrix' || rt == 'matrix3d'));
+ };
+ var leftResult = [];
+ var rightResult = [];
+ var types = [];
+
+ if (left.length != right.length) {
+ if (!matrixModulesLoaded)
+ return;
+ var merged = mergeMatrices(left, right);
+ leftResult = [merged[0]];
+ rightResult = [merged[1]];
+ types = [['matrix', [merged[2]]]];
+ } else {
+ for (var i = 0; i < left.length; i++) {
+ var leftType = left[i].t;
+ var rightType = right[i].t;
+ var leftArgs = left[i].d;
+ var rightArgs = right[i].d;
+
+ var leftFunctionData = transformFunctions[leftType];
+ var rightFunctionData = transformFunctions[rightType];
+
+ var type;
+ if (isMatrixOrPerspective(leftType, rightType)) {
+ if (!matrixModulesLoaded)
+ return;
+ var merged = mergeMatrices([left[i]], [right[i]]);
+ leftResult.push(merged[0]);
+ rightResult.push(merged[1]);
+ types.push(['matrix', [merged[2]]]);
+ continue;
+ } else if (leftType == rightType) {
+ type = leftType;
+ } else if (leftFunctionData[2] && rightFunctionData[2] && typeTo2D(leftType) == typeTo2D(rightType)) {
+ type = typeTo2D(leftType);
+ leftArgs = leftFunctionData[2](leftArgs);
+ rightArgs = rightFunctionData[2](rightArgs);
+ } else if (leftFunctionData[1] && rightFunctionData[1] && typeTo3D(leftType) == typeTo3D(rightType)) {
+ type = typeTo3D(leftType);
+ leftArgs = leftFunctionData[1](leftArgs);
+ rightArgs = rightFunctionData[1](rightArgs);
+ } else {
+ if (!matrixModulesLoaded)
+ return;
+ var merged = mergeMatrices(left, right);
+ leftResult = [merged[0]];
+ rightResult = [merged[1]];
+ types = [['matrix', [merged[2]]]];
+ break;
+ }
+
+ var leftArgsCopy = [];
+ var rightArgsCopy = [];
+ var stringConversions = [];
+ for (var j = 0; j < leftArgs.length; j++) {
+ var merge = typeof leftArgs[j] == 'number' ? scope.mergeNumbers : scope.mergeDimensions;
+ var merged = merge(leftArgs[j], rightArgs[j]);
+ leftArgsCopy[j] = merged[0];
+ rightArgsCopy[j] = merged[1];
+ stringConversions.push(merged[2]);
+ }
+ leftResult.push(leftArgsCopy);
+ rightResult.push(rightArgsCopy);
+ types.push([type, stringConversions]);
+ }
+ }
+
+ if (flipResults) {
+ var tmp = leftResult;
+ leftResult = rightResult;
+ rightResult = tmp;
+ }
+
+ return [leftResult, rightResult, function(list) {
+ return list.map(function(args, i) {
+ var stringifiedArgs = args.map(function(arg, j) {
+ return types[i][1][j](arg);
+ }).join(',');
+ if (types[i][0] == 'matrix' && stringifiedArgs.split(',').length == 16)
+ types[i][0] = 'matrix3d';
+ return types[i][0] + '(' + stringifiedArgs + ')';
+
+ }).join(' ');
+ }];
+ }
+
+ scope.addPropertiesHandler(parseTransform, mergeTransforms, ['transform']);
+
+ scope.transformToSvgMatrix = function(string) {
+ // matrix(<a> <b> <c> <d> <e> <f>)
+ var mat = scope.transformListToMatrix(parseTransform(string));
+ return 'matrix(' +
+ numberToLongString(mat[0]) + ' ' + // <a>
+ numberToLongString(mat[1]) + ' ' + // <b>
+ numberToLongString(mat[4]) + ' ' + // <c>
+ numberToLongString(mat[5]) + ' ' + // <d>
+ numberToLongString(mat[12]) + ' ' + // <e>
+ numberToLongString(mat[13]) + // <f>
+ ')';
+ };
+
+ if (WEB_ANIMATIONS_TESTING)
+ testing.parseTransform = parseTransform;
+
+})(webAnimations1, webAnimationsTesting);