Bug 1358011 - Part 1: Handle frames() timing function. r?pbro draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Tue, 06 Jun 2017 18:23:29 +0900
changeset 589882 23bd27dbec3be72d7d80fe4afbdc93b4a73f7c30
parent 589301 2c6289f56812c30254acfdddabcfec1e149c0336
child 589883 26d035842cc50bfc1b4f6ce024312308a6de58cb
push id62556
push userbmo:dakatsuka@mozilla.com
push dateWed, 07 Jun 2017 01:24:52 +0000
reviewerspbro
bugs1358011
milestone55.0a1
Bug 1358011 - Part 1: Handle frames() timing function. r?pbro MozReview-Commit-ID: CGIZONHWaqu
devtools/client/animationinspector/graph-helper.js
--- a/devtools/client/animationinspector/graph-helper.js
+++ b/devtools/client/animationinspector/graph-helper.js
@@ -511,19 +511,25 @@ function appendPathElement(parentEl, pat
     }
 
     if (i + 1 === pathSegments.length) {
       // We already create steps or cubic-bezier path string in previous.
       break;
     }
 
     const nextPathSegment = pathSegments[i + 1];
-    path += pathSegment.easing.startsWith("steps")
-            ? createStepsPathString(pathSegment, nextPathSegment)
-            : createCubicBezierPathString(pathSegment, nextPathSegment);
+    let createPathFunction;
+    if (pathSegment.easing.startsWith("steps")) {
+      createPathFunction = createStepsPathString;
+    } else if (pathSegment.easing.startsWith("frames")) {
+      createPathFunction = createFramesPathString;
+    } else {
+      createPathFunction = createCubicBezierPathString;
+    }
+    path += createPathFunction(pathSegment, nextPathSegment);
   }
   path += ` L${ pathSegments[pathSegments.length - 1].x },0`;
   if (isClosePathNeeded) {
     path += " Z";
   }
   // Append and return the path element.
   return createSVGNode({
     parent: parentEl,
@@ -589,16 +595,38 @@ function createStepsPathString(currentSe
   }
   if (!isStepStart) {
     path += ` L${ nextSegment.x },${ nextSegment.y }`;
   }
   return path;
 }
 
 /**
+ * Create a path string to represents a frames function.
+ * @param {Object} currentSegment - e.g. { x: 0, y: 0, easing: "frames(2)" }
+ * @param {Object} nextSegment - e.g. { x: 1, y: 1 }
+ * @return {String} path string - e.g. "C 0.25 0.1, 0.25 1, 1 1"
+ */
+function createFramesPathString(currentSegment, nextSegment) {
+  const matches =
+    currentSegment.easing.match(/^frames\((\d+)\)/);
+  const framesNumber = parseInt(matches[1], 10);
+  const oneFrameX = (nextSegment.x - currentSegment.x) / framesNumber;
+  const oneFrameY = (nextSegment.y - currentSegment.y) / (framesNumber - 1);
+  let path = "";
+  for (let frame = 0; frame < framesNumber; frame++) {
+    const sx = currentSegment.x + frame * oneFrameX;
+    const ex = sx + oneFrameX;
+    const y = currentSegment.y + frame * oneFrameY;
+    path += ` L${ sx },${ y } L${ ex },${ y }`;
+  }
+  return path;
+}
+
+/**
  * Create a path string to represents a bezier curve.
  * @param {Object} currentSegment - e.g. { x: 0, y: 0, easing: "ease" }
  * @param {Object} nextSegment - e.g. { x: 1, y: 1 }
  * @return {String} path string - e.g. "C 0.25 0.1, 0.25 1, 1 1"
  */
 function createCubicBezierPathString(currentSegment, nextSegment) {
   const controlPoints = parseTimingFunction(currentSegment.easing);
   if (!controlPoints) {
@@ -679,14 +707,14 @@ function getPreferredKeyframesProgressTh
 exports.getPreferredKeyframesProgressThreshold = getPreferredKeyframesProgressThreshold;
 
 /**
  * Return preferred progress threshold to render summary graph.
  * @param {String} - easing e.g. steps(2), linear and so on.
  * @return {float} - preferred threshold.
  */
 function getPreferredProgressThreshold(easing) {
-  const stepFunction = easing.match(/steps\((\d+)/);
-  return stepFunction
-       ? 1 / (parseInt(stepFunction[1], 10) + 1)
+  const stepOrFramesFunction = easing.match(/(steps|frames)\((\d+)/);
+  return stepOrFramesFunction
+       ? 1 / (parseInt(stepOrFramesFunction[2], 10) + 1)
        : DEFAULT_MIN_PROGRESS_THRESHOLD;
 }
 exports.getPreferredProgressThreshold = getPreferredProgressThreshold;