aboutsummaryrefslogtreecommitdiff
path: root/catapult/third_party/polymer/components/web-animations-js/src/dimension-handler.js
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/third_party/polymer/components/web-animations-js/src/dimension-handler.js')
-rw-r--r--catapult/third_party/polymer/components/web-animations-js/src/dimension-handler.js240
1 files changed, 240 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/web-animations-js/src/dimension-handler.js b/catapult/third_party/polymer/components/web-animations-js/src/dimension-handler.js
new file mode 100644
index 00000000..9e487f97
--- /dev/null
+++ b/catapult/third_party/polymer/components/web-animations-js/src/dimension-handler.js
@@ -0,0 +1,240 @@
+// 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) {
+
+ // Evaluates a calc expression.
+ // https://drafts.csswg.org/css-values-3/#calc-notation
+ function calculate(expression) {
+ // In calc expressions, white space is required on both sides of the
+ // + and - operators. https://drafts.csswg.org/css-values-3/#calc-notation
+ // Thus any + or - immediately adjacent to . or 0..9 is part of the number,
+ // e.g. -1.23e+45
+ // This regular expression matches ( ) * / + - and numbers.
+ var tokenRegularExpression = /([\+\-\w\.]+|[\(\)\*\/])/g;
+ var currentToken;
+ function consume() {
+ var matchResult = tokenRegularExpression.exec(expression);
+ if (matchResult)
+ currentToken = matchResult[0];
+ else
+ currentToken = undefined;
+ }
+ consume(); // Read the initial token.
+
+ function calcNumber() {
+ // https://drafts.csswg.org/css-values-3/#number-value
+ var result = Number(currentToken);
+ consume();
+ return result;
+ }
+
+ function calcValue() {
+ // <calc-value> = <number> | <dimension> | <percentage> | ( <calc-sum> )
+ if (currentToken !== '(')
+ return calcNumber();
+ consume();
+ var result = calcSum();
+ if (currentToken !== ')')
+ return NaN;
+ consume();
+ return result;
+ }
+
+ function calcProduct() {
+ // <calc-product> = <calc-value> [ '*' <calc-value> | '/' <calc-number-value> ]*
+ var left = calcValue();
+ while (currentToken === '*' || currentToken === '/') {
+ var operator = currentToken;
+ consume();
+ var right = calcValue();
+ if (operator === '*')
+ left *= right;
+ else
+ left /= right;
+ }
+ return left;
+ }
+
+ function calcSum() {
+ // <calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
+ var left = calcProduct();
+ while (currentToken === '+' || currentToken === '-') {
+ var operator = currentToken;
+ consume();
+ var right = calcProduct();
+ if (operator === '+')
+ left += right;
+ else
+ left -= right;
+ }
+ return left;
+ }
+
+ // <calc()> = calc( <calc-sum> )
+ return calcSum();
+ }
+
+ function parseDimension(unitRegExp, string) {
+ string = string.trim().toLowerCase();
+
+ if (string == '0' && 'px'.search(unitRegExp) >= 0)
+ return {px: 0};
+
+ // If we have parenthesis, we're a calc and need to start with 'calc'.
+ if (!/^[^(]*$|^calc/.test(string))
+ return;
+ string = string.replace(/calc\(/g, '(');
+
+ // We tag units by prefixing them with 'U' (note that we are already
+ // lowercase) to prevent problems with types which are substrings of
+ // each other (although prefixes may be problematic!)
+ var matchedUnits = {};
+ string = string.replace(unitRegExp, function(match) {
+ matchedUnits[match] = null;
+ return 'U' + match;
+ });
+ var taggedUnitRegExp = 'U(' + unitRegExp.source + ')';
+
+ // Validating input is simply applying as many reductions as we can.
+ var typeCheck = string.replace(/[-+]?(\d*\.)?\d+([Ee][-+]?\d+)?/g, 'N')
+ .replace(new RegExp('N' + taggedUnitRegExp, 'g'), 'D')
+ .replace(/\s[+-]\s/g, 'O')
+ .replace(/\s/g, '');
+ var reductions = [/N\*(D)/g, /(N|D)[*/]N/g, /(N|D)O\1/g, /\((N|D)\)/g];
+ var i = 0;
+ while (i < reductions.length) {
+ if (reductions[i].test(typeCheck)) {
+ typeCheck = typeCheck.replace(reductions[i], '$1');
+ i = 0;
+ } else {
+ i++;
+ }
+ }
+ if (typeCheck != 'D')
+ return;
+
+ for (var unit in matchedUnits) {
+ var result = calculate(string.replace(new RegExp('U' + unit, 'g'), '').replace(new RegExp(taggedUnitRegExp, 'g'), '*0'));
+ if (!isFinite(result))
+ return;
+ matchedUnits[unit] = result;
+ }
+ return matchedUnits;
+ }
+
+ function mergeDimensionsNonNegative(left, right) {
+ return mergeDimensions(left, right, true);
+ }
+
+ function mergeDimensions(left, right, nonNegative) {
+ var units = [], unit;
+ for (unit in left)
+ units.push(unit);
+ for (unit in right) {
+ if (units.indexOf(unit) < 0)
+ units.push(unit);
+ }
+
+ left = units.map(function(unit) { return left[unit] || 0; });
+ right = units.map(function(unit) { return right[unit] || 0; });
+ return [left, right, function(values) {
+ var result = values.map(function(value, i) {
+ if (values.length == 1 && nonNegative) {
+ value = Math.max(value, 0);
+ }
+ // Scientific notation (e.g. 1e2) is not yet widely supported by browser vendors.
+ return scope.numberToString(value) + units[i];
+ }).join(' + ');
+ return values.length > 1 ? 'calc(' + result + ')' : result;
+ }];
+ }
+
+ var lengthUnits = 'px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc';
+ var parseLength = parseDimension.bind(null, new RegExp(lengthUnits, 'g'));
+ var parseLengthOrPercent = parseDimension.bind(null, new RegExp(lengthUnits + '|%', 'g'));
+ var parseAngle = parseDimension.bind(null, /deg|rad|grad|turn/g);
+
+ scope.parseLength = parseLength;
+ scope.parseLengthOrPercent = parseLengthOrPercent;
+ scope.consumeLengthOrPercent = scope.consumeParenthesised.bind(null, parseLengthOrPercent);
+ scope.parseAngle = parseAngle;
+ scope.mergeDimensions = mergeDimensions;
+
+ var consumeLength = scope.consumeParenthesised.bind(null, parseLength);
+ var consumeSizePair = scope.consumeRepeated.bind(undefined, consumeLength, /^/);
+ var consumeSizePairList = scope.consumeRepeated.bind(undefined, consumeSizePair, /^,/);
+ scope.consumeSizePairList = consumeSizePairList;
+
+ var parseSizePairList = function(input) {
+ var result = consumeSizePairList(input);
+ if (result && result[1] == '') {
+ return result[0];
+ }
+ };
+
+ var mergeNonNegativeSizePair = scope.mergeNestedRepeated.bind(undefined, mergeDimensionsNonNegative, ' ');
+ var mergeNonNegativeSizePairList = scope.mergeNestedRepeated.bind(undefined, mergeNonNegativeSizePair, ',');
+ scope.mergeNonNegativeSizePair = mergeNonNegativeSizePair;
+
+ scope.addPropertiesHandler(parseSizePairList, mergeNonNegativeSizePairList, [
+ 'background-size'
+ ]);
+
+ scope.addPropertiesHandler(parseLengthOrPercent, mergeDimensionsNonNegative, [
+ 'border-bottom-width',
+ 'border-image-width',
+ 'border-left-width',
+ 'border-right-width',
+ 'border-top-width',
+ 'flex-basis',
+ 'font-size',
+ 'height',
+ 'line-height',
+ 'max-height',
+ 'max-width',
+ 'outline-width',
+ 'width',
+ ]);
+
+ scope.addPropertiesHandler(parseLengthOrPercent, mergeDimensions, [
+ 'border-bottom-left-radius',
+ 'border-bottom-right-radius',
+ 'border-top-left-radius',
+ 'border-top-right-radius',
+ 'bottom',
+ 'left',
+ 'letter-spacing',
+ 'margin-bottom',
+ 'margin-left',
+ 'margin-right',
+ 'margin-top',
+ 'min-height',
+ 'min-width',
+ 'outline-offset',
+ 'padding-bottom',
+ 'padding-left',
+ 'padding-right',
+ 'padding-top',
+ 'perspective',
+ 'right',
+ 'shape-margin',
+ 'stroke-dashoffset',
+ 'text-indent',
+ 'top',
+ 'vertical-align',
+ 'word-spacing',
+ ]);
+
+})(webAnimations1, webAnimationsTesting);