Bug 1412555 - Update canvas position on scroll in the css grid highlighter. r=pbro draft
authorGabriel Luong <gabriel.luong@gmail.com>
Sat, 28 Oct 2017 16:07:40 -0400
changeset 688196 8c8c84245054437aebdd2de22740fb9a7e41d2ea
parent 688194 5da48a1cd6d684bf431d7766303c8d6ad56380fc
child 737809 7883e661b80366ff2d3e05aef44653d2672ca9f8
push id86685
push userbmo:gl@mozilla.com
push dateSat, 28 Oct 2017 20:07:55 +0000
reviewerspbro
bugs1412555
milestone58.0a1
Bug 1412555 - Update canvas position on scroll in the css grid highlighter. r=pbro MozReview-Commit-ID: GKAQ8LRfLau
devtools/server/actors/highlighters/css-grid.js
devtools/server/actors/highlighters/flexbox.js
devtools/server/actors/highlighters/utils/canvas.js
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -8,21 +8,21 @@ const Services = require("Services");
 const { AutoRefreshHighlighter } = require("./auto-refresh");
 const {
   CANVAS_SIZE,
   drawBubbleRect,
   drawLine,
   drawRect,
   drawRoundedRect,
   getBoundsFromPoints,
-  getCanvasPosition,
   getCurrentMatrix,
   getPathDescriptionFromPoints,
   getPointsFromDiagonal,
   updateCanvasElement,
+  updateCanvasPosition,
 } = require("./utils/canvas");
 const {
   CanvasFrameAnonymousContentHelper,
   createNode,
   createSVGNode,
   moveInfobar,
 } = require("./utils/markup");
 const { apply } = require("devtools/shared/layout/dom-matrix-2d");
@@ -171,22 +171,20 @@ class CssGridHighlighter extends AutoRef
     pageListenerTarget.addEventListener("pagehide", this.onPageHide);
 
     // Initialize the <canvas> position to the top left corner of the page
     this._canvasPosition = {
       x: 0,
       y: 0
     };
 
-    // Calling `getCanvasPosition` anyway since the highlighter could be initialized
+    // Calling `updateCanvasPosition` anyway since the highlighter could be initialized
     // on a page that has scrolled already.
-    let { canvasX, canvasY } = getCanvasPosition(this._canvasPosition, this._scroll,
-      this.win, this._winDimensions);
-    this._canvasPosition.x = canvasX;
-    this._canvasPosition.y = canvasY;
+    updateCanvasPosition(this._canvasPosition, this._scroll, this.win,
+      this._winDimensions);
   }
 
   _buildMarkup() {
     let container = createNode(this.win, {
       attributes: {
         "class": "highlighter-container"
       }
     });
@@ -767,17 +765,17 @@ class CssGridHighlighter extends AutoRef
       getBoundsFromPoints([{x, y}, {x, y}, {x, y}, {x, y}]), this.win);
   }
 
   /**
    * The <canvas>'s position needs to be updated if the page scrolls too much, in order
    * to give the illusion that it always covers the viewport.
    */
   _scrollUpdate() {
-    let { hasUpdated } = getCanvasPosition(this._canvasPosition, this._scroll, this.win,
+    let hasUpdated = updateCanvasPosition(this._canvasPosition, this._scroll, this.win,
       this._winDimensions);
 
     if (hasUpdated) {
       this._update();
     }
   }
 
   getFirstRowLinePos(fragment) {
--- a/devtools/server/actors/highlighters/flexbox.js
+++ b/devtools/server/actors/highlighters/flexbox.js
@@ -2,19 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { AutoRefreshHighlighter } = require("./auto-refresh");
 const {
   CANVAS_SIZE,
-  getCanvasPosition,
   getCurrentMatrix,
   updateCanvasElement,
+  updateCanvasPosition,
 } = require("./utils/canvas");
 const {
   CanvasFrameAnonymousContentHelper,
   createNode,
 } = require("./utils/markup");
 const {
   setIgnoreLayoutChanges,
 } = require("devtools/shared/layout/utils");
@@ -37,22 +37,20 @@ class FlexboxHighlighter extends AutoRef
     pageListenerTarget.addEventListener("pagehide", this.onPageHide);
 
     // Initialize the <canvas> position to the top left corner of the page
     this._canvasPosition = {
       x: 0,
       y: 0
     };
 
-    // Calling `getCanvasPosition` anyway since the highlighter could be initialized
+    // Calling `updateCanvasPosition` anyway since the highlighter could be initialized
     // on a page that has scrolled already.
-    let { canvasX, canvasY } = getCanvasPosition(this._canvasPosition, this._scroll,
-      this.win, this._winDimensions);
-    this._canvasPosition.x = canvasX;
-    this._canvasPosition.y = canvasY;
+    updateCanvasPosition(this._canvasPosition, this._scroll, this.win,
+      this._winDimensions);
   }
 
   _buildMarkup() {
     let container = createNode(this.win, {
       attributes: {
         "class": "highlighter-container"
       }
     });
@@ -121,17 +119,17 @@ class FlexboxHighlighter extends AutoRef
     this.getElement("canvas").setAttribute("hidden", "true");
   }
 
   /**
    * The <canvas>'s position needs to be updated if the page scrolls too much, in order
    * to give the illusion that it always covers the viewport.
    */
   _scrollUpdate() {
-    let { hasUpdated } = getCanvasPosition(this._canvasPosition, this._scroll, this.win,
+    let hasUpdated = updateCanvasPosition(this._canvasPosition, this._scroll, this.win,
       this._winDimensions);
 
     if (hasUpdated) {
       this._update();
     }
   }
 
   _show() {
--- a/devtools/server/actors/highlighters/utils/canvas.js
+++ b/devtools/server/actors/highlighters/utils/canvas.js
@@ -224,89 +224,16 @@ function getBoundsFromPoints(points) {
   bounds.y = bounds.top;
   bounds.width = bounds.right - bounds.left;
   bounds.height = bounds.bottom - bounds.top;
 
   return bounds;
 }
 
 /**
- * Calculates and returns the <canvas>'s position in accordance with the page's scroll,
- * document's size, canvas size, and viewport's size. This is called when a page's scroll
- * is detected.
- *
- * @param  {Object} canvasPosition
- *         A pointer object {x, y} representing the <canvas> position to the top left
- *         corner of the page.
- * @param  {Object} scrollPosition
- *         A pointer object {x, y} representing the window's pageXOffset and pageYOffset.
- * @param  {Window} window
- *         The window object.
- * @param  {Object} windowDimensions
- *         An object {width, height} representing the window's dimensions for the
- *         `window` given.
- * @return {Object} An object with the following properties:
- *         - {Boolean} hasUpdated
- *           true if the <canvas> position was updated and false otherwise.
- *         - {Number} canvasX
- *           The canvas' x position.
- *         - {Number} canvasY
- *           The canvas' y position.
- */
-function getCanvasPosition(canvasPosition, scrollPosition, window, windowDimensions) {
-  let { x: canvasX, y: canvasY } = canvasPosition;
-  let { x: scrollX, y: scrollY } = scrollPosition;
-  let cssCanvasSize = CANVAS_SIZE / window.devicePixelRatio;
-  let viewportSize = getViewportDimensions(window);
-  let { height, width } = windowDimensions;
-  let canvasWidth = cssCanvasSize;
-  let canvasHeight = cssCanvasSize;
-  let hasUpdated = false;
-
-  // Those values indicates the relative horizontal and vertical space the page can
-  // scroll before we have to reposition the <canvas>; they're 1/4 of the delta between
-  // the canvas' size and the viewport's size: that's because we want to consider both
-  // sides (top/bottom, left/right; so 1/2 for each side) and also we don't want to
-  // shown the edges of the canvas in case of fast scrolling (to avoid showing undraw
-  // areas, therefore another 1/2 here).
-  let bufferSizeX = (canvasWidth - viewportSize.width) >> 2;
-  let bufferSizeY = (canvasHeight - viewportSize.height) >> 2;
-
-  // Defines the boundaries for the canvas.
-  let leftBoundary = 0;
-  let rightBoundary = width - canvasWidth;
-  let topBoundary = 0;
-  let bottomBoundary = height - canvasHeight;
-
-  // Defines the thresholds that triggers the canvas' position to be updated.
-  let leftThreshold = scrollX - bufferSizeX;
-  let rightThreshold = scrollX - canvasWidth + viewportSize.width + bufferSizeX;
-  let topThreshold = scrollY - bufferSizeY;
-  let bottomThreshold = scrollY - canvasHeight + viewportSize.height + bufferSizeY;
-
-  if (canvasX < rightBoundary && canvasX < rightThreshold) {
-    canvasX = Math.min(leftThreshold, rightBoundary);
-    hasUpdated = true;
-  } else if (canvasX > leftBoundary && canvasX > leftThreshold) {
-    canvasX = Math.max(rightThreshold, leftBoundary);
-    hasUpdated = true;
-  }
-
-  if (canvasY < bottomBoundary && canvasY < bottomThreshold) {
-    canvasY = Math.min(topThreshold, bottomBoundary);
-    hasUpdated = true;
-  } else if (canvasY > topBoundary && canvasY > topThreshold) {
-    canvasY = Math.max(bottomThreshold, topBoundary);
-    hasUpdated = true;
-  }
-
-  return { canvasX, canvasY, hasUpdated };
-}
-
-/**
  * Returns the current matrices for both canvas drawing and SVG taking into account the
  * following transformations, in this order:
  *   1. The scale given by the display pixel ratio.
  *   2. The translation to the top left corner of the element.
  *   3. The scale given by the current zoom.
  *   4. The translation given by the top and left padding of the element.
  *   5. Any CSS transformation applied directly to the element (only 2D
  *      transformation; the 3D transformation are flattened, see `dom-matrix-2d` module
@@ -422,19 +349,90 @@ function updateCanvasElement(canvas, can
 
   // Resize the canvas taking the dpr into account so as to have crisp lines, and
   // translating it to give the perception that it always covers the viewport.
   canvas.setAttribute("style",
     `width: ${size}px; height: ${size}px; transform: translate(${x}px, ${y}px);`);
   canvas.getCanvasContext("2d").clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
 }
 
+/**
+ * Calculates and returns the <canvas>'s position in accordance with the page's scroll,
+ * document's size, canvas size, and viewport's size. This is called when a page's scroll
+ * is detected.
+ *
+ * @param  {Object} canvasPosition
+ *         A pointer object {x, y} representing the <canvas> position to the top left
+ *         corner of the page.
+ * @param  {Object} scrollPosition
+ *         A pointer object {x, y} representing the window's pageXOffset and pageYOffset.
+ * @param  {Window} window
+ *         The window object.
+ * @param  {Object} windowDimensions
+ *         An object {width, height} representing the window's dimensions for the
+ *         `window` given.
+ * @return {Boolean} true if the <canvas> position was updated and false otherwise.
+ */
+function updateCanvasPosition(canvasPosition, scrollPosition, window, windowDimensions) {
+  let { x: canvasX, y: canvasY } = canvasPosition;
+  let { x: scrollX, y: scrollY } = scrollPosition;
+  let cssCanvasSize = CANVAS_SIZE / window.devicePixelRatio;
+  let viewportSize = getViewportDimensions(window);
+  let { height, width } = windowDimensions;
+  let canvasWidth = cssCanvasSize;
+  let canvasHeight = cssCanvasSize;
+  let hasUpdated = false;
+
+  // Those values indicates the relative horizontal and vertical space the page can
+  // scroll before we have to reposition the <canvas>; they're 1/4 of the delta between
+  // the canvas' size and the viewport's size: that's because we want to consider both
+  // sides (top/bottom, left/right; so 1/2 for each side) and also we don't want to
+  // shown the edges of the canvas in case of fast scrolling (to avoid showing undraw
+  // areas, therefore another 1/2 here).
+  let bufferSizeX = (canvasWidth - viewportSize.width) >> 2;
+  let bufferSizeY = (canvasHeight - viewportSize.height) >> 2;
+
+  // Defines the boundaries for the canvas.
+  let leftBoundary = 0;
+  let rightBoundary = width - canvasWidth;
+  let topBoundary = 0;
+  let bottomBoundary = height - canvasHeight;
+
+  // Defines the thresholds that triggers the canvas' position to be updated.
+  let leftThreshold = scrollX - bufferSizeX;
+  let rightThreshold = scrollX - canvasWidth + viewportSize.width + bufferSizeX;
+  let topThreshold = scrollY - bufferSizeY;
+  let bottomThreshold = scrollY - canvasHeight + viewportSize.height + bufferSizeY;
+
+  if (canvasX < rightBoundary && canvasX < rightThreshold) {
+    canvasX = Math.min(leftThreshold, rightBoundary);
+    hasUpdated = true;
+  } else if (canvasX > leftBoundary && canvasX > leftThreshold) {
+    canvasX = Math.max(rightThreshold, leftBoundary);
+    hasUpdated = true;
+  }
+
+  if (canvasY < bottomBoundary && canvasY < bottomThreshold) {
+    canvasY = Math.min(topThreshold, bottomBoundary);
+    hasUpdated = true;
+  } else if (canvasY > topBoundary && canvasY > topThreshold) {
+    canvasY = Math.max(bottomThreshold, topBoundary);
+    hasUpdated = true;
+  }
+
+  // Update the canvas position with the calculated canvasX and canvasY positions.
+  canvasPosition.x = canvasX;
+  canvasPosition.y = canvasY;
+
+  return hasUpdated;
+}
+
 exports.CANVAS_SIZE = CANVAS_SIZE;
 exports.drawBubbleRect = drawBubbleRect;
 exports.drawLine = drawLine;
 exports.drawRect = drawRect;
 exports.drawRoundedRect = drawRoundedRect;
 exports.getBoundsFromPoints = getBoundsFromPoints;
-exports.getCanvasPosition = getCanvasPosition;
 exports.getCurrentMatrix = getCurrentMatrix;
 exports.getPathDescriptionFromPoints = getPathDescriptionFromPoints;
 exports.getPointsFromDiagonal = getPointsFromDiagonal;
 exports.updateCanvasElement = updateCanvasElement;
+exports.updateCanvasPosition = updateCanvasPosition;