Index: third_party/polymer/components/web-animations-js/src/dimension-handler.js |
diff --git a/third_party/polymer/components/web-animations-js/src/dimension-handler.js b/third_party/polymer/components/web-animations-js/src/dimension-handler.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9e487f972a8691ae1760457a57841e0b3b8edd40 |
--- /dev/null |
+++ b/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); |