Pull web-animations-js into third-party via the third_party/polymer/reproduce.sh...
[chromium-blink-merge.git] / third_party / web-animations-js / sources / src / dimension-handler.js
blob66afe0d2e2d547881877ecd00245c62ad3bb1ed6
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 //   You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 //   See the License for the specific language governing permissions and
13 // limitations under the License.
15 (function(scope, testing) {
17   function parseDimension(unitRegExp, string) {
18     string = string.trim().toLowerCase();
20     if (string == '0' && 'px'.search(unitRegExp) >= 0)
21       return {px: 0};
23     // If we have parenthesis, we're a calc and need to start with 'calc'.
24     if (!/^[^(]*$|^calc/.test(string))
25       return;
26     string = string.replace(/calc\(/g, '(');
28     // We tag units by prefixing them with 'U' (note that we are already
29     // lowercase) to prevent problems with types which are substrings of
30     // each other (although prefixes may be problematic!)
31     var matchedUnits = {};
32     string = string.replace(unitRegExp, function(match) {
33       matchedUnits[match] = null;
34       return 'U' + match;
35     });
36     var taggedUnitRegExp = 'U(' + unitRegExp.source + ')';
38     // Validating input is simply applying as many reductions as we can.
39     var typeCheck = string.replace(/[-+]?(\d*\.)?\d+/g, 'N')
40                           .replace(new RegExp('N' + taggedUnitRegExp, 'g'), 'D')
41                           .replace(/\s[+-]\s/g, 'O')
42                           .replace(/\s/g, '');
43     var reductions = [/N\*(D)/g, /(N|D)[*/]N/g, /(N|D)O\1/g, /\((N|D)\)/g];
44     var i = 0;
45     while (i < reductions.length) {
46       if (reductions[i].test(typeCheck)) {
47         typeCheck = typeCheck.replace(reductions[i], '$1');
48         i = 0;
49       } else {
50         i++;
51       }
52     }
53     if (typeCheck != 'D')
54       return;
56     for (var unit in matchedUnits) {
57       var result = eval(string.replace(new RegExp('U' + unit, 'g'), '').replace(new RegExp(taggedUnitRegExp, 'g'), '*0'));
58       if (!isFinite(result))
59         return;
60       matchedUnits[unit] = result;
61     }
62     return matchedUnits;
63   }
65   function mergeDimensionsNonNegative(left, right) {
66     return mergeDimensions(left, right, true);
67   }
69   function mergeDimensions(left, right, nonNegative) {
70     var units = [], unit;
71     for (unit in left)
72       units.push(unit);
73     for (unit in right) {
74       if (units.indexOf(unit) < 0)
75         units.push(unit);
76     }
78     left = units.map(function(unit) { return left[unit] || 0; });
79     right = units.map(function(unit) { return right[unit] || 0; });
80     return [left, right, function(values) {
81       var result = values.map(function(value, i) {
82         if (values.length == 1 && nonNegative) {
83           value = Math.max(value, 0);
84         }
85         // Scientific notation (e.g. 1e2) is not yet widely supported by browser vendors.
86         return scope.numberToString(value) + units[i];
87       }).join(' + ');
88       return values.length > 1 ? 'calc(' + result + ')' : result;
89     }];
90   }
92   var lengthUnits = 'px|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc';
93   var parseLength = parseDimension.bind(null, new RegExp(lengthUnits, 'g'));
94   var parseLengthOrPercent = parseDimension.bind(null, new RegExp(lengthUnits + '|%', 'g'));
95   var parseAngle = parseDimension.bind(null, /deg|rad|grad|turn/g);
97   scope.parseLength = parseLength;
98   scope.parseLengthOrPercent = parseLengthOrPercent;
99   scope.consumeLengthOrPercent = scope.consumeParenthesised.bind(null, parseLengthOrPercent);
100   scope.parseAngle = parseAngle;
101   scope.mergeDimensions = mergeDimensions;
103   var consumeLength = scope.consumeParenthesised.bind(null, parseLength);
104   var consumeSizePair = scope.consumeRepeated.bind(undefined, consumeLength, /^/);
105   var consumeSizePairList = scope.consumeRepeated.bind(undefined, consumeSizePair, /^,/);
106   scope.consumeSizePairList = consumeSizePairList;
108   var parseSizePairList = function(input) {
109     var result = consumeSizePairList(input);
110     if (result && result[1] == '') {
111       return result[0];
112     }
113   };
115   var mergeNonNegativeSizePair = scope.mergeNestedRepeated.bind(undefined, mergeDimensionsNonNegative, ' ');
116   var mergeNonNegativeSizePairList = scope.mergeNestedRepeated.bind(undefined, mergeNonNegativeSizePair, ',');
117   scope.mergeNonNegativeSizePair = mergeNonNegativeSizePair;
119   scope.addPropertiesHandler(parseSizePairList, mergeNonNegativeSizePairList, [
120     'background-size'
121   ]);
123   scope.addPropertiesHandler(parseLengthOrPercent, mergeDimensionsNonNegative, [
124     'border-bottom-width',
125     'border-image-width',
126     'border-left-width',
127     'border-right-width',
128     'border-top-width',
129     'flex-basis',
130     'font-size',
131     'height',
132     'line-height',
133     'max-height',
134     'max-width',
135     'outline-width',
136     'width',
137   ]);
139   scope.addPropertiesHandler(parseLengthOrPercent, mergeDimensions, [
140     'border-bottom-left-radius',
141     'border-bottom-right-radius',
142     'border-top-left-radius',
143     'border-top-right-radius',
144     'bottom',
145     'left',
146     'letter-spacing',
147     'margin-bottom',
148     'margin-left',
149     'margin-right',
150     'margin-top',
151     'min-height',
152     'min-width',
153     'outline-offset',
154     'padding-bottom',
155     'padding-left',
156     'padding-right',
157     'padding-top',
158     'perspective',
159     'right',
160     'shape-margin',
161     'text-indent',
162     'top',
163     'vertical-align',
164     'word-spacing',
165   ]);
167 })(webAnimations1, webAnimationsTesting);