| function roundNumbers(value, digits) { |
| // Round numbers to |digits| decimal places. |
| return value. |
| replace(/-?\d*\.\d+(e-?\d+)?/g, function(n) { |
| return (parseFloat(n).toFixed(digits)). |
| replace(/\.\d+/, function(m) { |
| return m.replace(/0+$/, ''); |
| }). |
| replace(/\.$/, ''). |
| replace(/^-0$/, '0'); |
| }); |
| } |
| |
| function normalizeValue(value, digits) { |
| // Round numbers and place whitespace between tokens. |
| return roundNumbers(value, digits). |
| replace(/([\w\d.]+|[^\s])/g, '$1 '). |
| replace(/\s+/g, ' '); |
| } |
| |
| // Transform a path seg list into a path string, rounding numbers to |digits| |
| // decimal places. |
| function serializePathSegList(list, digits) { |
| function segmentArguments(segment) { |
| const kCommandDescriptor = { |
| 'M': ['x', 'y'], |
| 'L': ['x', 'y'], |
| 'C': ['x1', 'y1', 'x2', 'y2', 'x', 'y'], |
| 'Q': ['x1', 'y1', 'x', 'y'], |
| 'S': ['x2', 'y2', 'x', 'y'], |
| 'T': ['x', 'y'], |
| 'A': ['r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag', 'x', 'y'], |
| 'H': ['x'], |
| 'V': ['y'], |
| 'Z': [] |
| }; |
| let command = segment.pathSegTypeAsLetter.toUpperCase(); |
| return kCommandDescriptor[command].map(field => { |
| return Number(segment[field]).toFixed(digits); |
| }); |
| } |
| return Array.from(list).map(segment => { |
| let command = segment.pathSegTypeAsLetter; |
| if (command === 'z') |
| command = 'Z'; |
| return [command, ...segmentArguments(segment)].join(' '); |
| }).join(' '); |
| } |
| |
| function normalizeProperty(path_string) { |
| let probePathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path'); |
| probePathElement.setAttribute('d', path_string); |
| document.documentElement.appendChild(probePathElement); |
| let string = getComputedStyle(probePathElement).getPropertyValue('d'); |
| probePathElement.remove(); |
| return string; |
| } |
| |
| // Assert that the animated path data of |target| matches that of |
| // |expected_path_string|. Numbers will be rounded to 2 decimal places. |
| function assert_animated_path_equals(target, expected_path_string) { |
| const kDecimals = 2; |
| let expected, actual; |
| if ('animatedPathSegList' in target) { |
| let probePathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path'); |
| probePathElement.setAttribute('d', expected_path_string); |
| expected = serializePathSegList(probePathElement.pathSegList, kDecimals) |
| actual = serializePathSegList(target.animatedPathSegList, kDecimals); |
| } else if ('d' in target.style) { |
| expected = normalizeValue(normalizeProperty(expected_path_string), kDecimals); |
| actual = normalizeValue(getComputedStyle(target).getPropertyValue('d'), kDecimals); |
| } else { |
| assert_unreached('no animated path data'); |
| } |
| assert_equals(actual, expected); |
| } |