Bug 1478481 - Flexbox highlighter overlay is wrong size, in page with full-page-zoom applied r=gl
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Wed, 10 Oct 2018 23:59:45 +0000
changeset 489133 7a275e7abf9b88e0d70a14e5a3dea3a7a8ce21e0
parent 489132 8878ac1f9f36c00d902b7a5d4e636ffbbc9217de
child 489134 122ac3c6e1dc29aeb824845419658dfd6c45604a
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewersgl
bugs1478481
milestone64.0a1
Bug 1478481 - Flexbox highlighter overlay is wrong size, in page with full-page-zoom applied r=gl - Added AutoRefreshHighlighter flag to AutoRefreshHighlighter. This ensures that getQuads() ignores the zoom factor. Differential Revision: https://phabricator.services.mozilla.com/D7599
devtools/server/actors/highlighters/auto-refresh.js
devtools/server/actors/highlighters/flexbox.js
devtools/shared/layout/utils.js
--- a/devtools/server/actors/highlighters/auto-refresh.js
+++ b/devtools/server/actors/highlighters/auto-refresh.js
@@ -73,16 +73,18 @@ function AutoRefreshHighlighter(highligh
 
   this._winDimensions = getWindowDimensions(this.win);
   this._scroll = { x: this.win.pageXOffset, y: this.win.pageYOffset };
 
   this.update = this.update.bind(this);
 }
 
 AutoRefreshHighlighter.prototype = {
+  _ignoreZoom: false,
+
   /**
    * Window corresponding to the current highlighterEnv
    */
   get win() {
     if (!this.highlighterEnv) {
       return null;
     }
     return this.highlighterEnv.window;
@@ -172,17 +174,17 @@ AutoRefreshHighlighter.prototype = {
    * Update the stored box quads by reading the current node's box quads.
    */
   _updateAdjustedQuads: function() {
     this.currentQuads = {};
 
     for (const region of BOX_MODEL_REGIONS) {
       this.currentQuads[region] = getAdjustedQuads(
         this.win,
-        this.currentNode, region);
+        this.currentNode, region, {ignoreZoom: this._ignoreZoom});
     }
   },
 
   /**
    * Update the knowledge we have of the current node's boxquads and return true
    * if any of the points x/y or bounds have change since.
    * @return {Boolean}
    */
--- a/devtools/server/actors/highlighters/flexbox.js
+++ b/devtools/server/actors/highlighters/flexbox.js
@@ -18,16 +18,17 @@ const {
 } = require("./utils/canvas");
 const {
   CanvasFrameAnonymousContentHelper,
   createNode,
   getComputedStyle,
 } = require("./utils/markup");
 const {
   getAdjustedQuads,
+  getCurrentZoom,
   getDisplayPixelRatio,
   getWindowDimensions,
   setIgnoreLayoutChanges,
 } = require("devtools/shared/layout/utils");
 
 const FLEXBOX_LINES_PROPERTIES = {
   "edge": {
     lineDash: [12, 10]
@@ -84,16 +85,18 @@ 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
     };
 
+    this._ignoreZoom = true;
+
     // Calling `updateCanvasPosition` anyway since the highlighter could be initialized
     // on a page that has scrolled already.
     updateCanvasPosition(this._canvasPosition, this._scroll, this.win,
       this._winDimensions);
   }
 
   _buildMarkup() {
     const container = createNode(this.win, {
@@ -243,19 +246,21 @@ class FlexboxHighlighter extends AutoRef
 
     if (gCachedFlexboxPattern.has(JUSTIFY_CONTENT)) {
       return gCachedFlexboxPattern.get(JUSTIFY_CONTENT);
     }
 
     // Create the inversed diagonal lines pattern
     // for the rendering the justify content gaps.
     const canvas = createNode(this.win, { nodeType: "canvas" });
-    const width = canvas.width = FLEXBOX_JUSTIFY_CONTENT_PATTERN_WIDTH * devicePixelRatio;
-    const height = canvas.height = FLEXBOX_JUSTIFY_CONTENT_PATTERN_HEIGHT *
-      devicePixelRatio;
+    const zoom = getCurrentZoom(this.win);
+    const width = canvas.width =
+      FLEXBOX_JUSTIFY_CONTENT_PATTERN_WIDTH * devicePixelRatio * zoom;
+    const height = canvas.height =
+      FLEXBOX_JUSTIFY_CONTENT_PATTERN_HEIGHT * devicePixelRatio * zoom;
 
     const ctx = canvas.getContext("2d");
     ctx.save();
     ctx.setLineDash(FLEXBOX_CONTAINER_PATTERN_LINE_DISH);
     ctx.beginPath();
     ctx.translate(.5, .5);
 
     ctx.moveTo(0, height);
@@ -378,18 +383,19 @@ class FlexboxHighlighter extends AutoRef
     if (!this.options.showAlignment || !this.flexData ||
         !this.currentQuads.content || !this.currentQuads.content[0]) {
       return;
     }
 
     const { devicePixelRatio } = this.win;
     const lineWidth = getDisplayPixelRatio(this.win);
     const offset = (lineWidth / 2) % 1;
-    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
-    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
+    const zoom = getCurrentZoom(this.win);
+    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio * zoom);
+    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio * zoom);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.alignItems.lineDash);
     this.ctx.lineWidth = lineWidth * 3;
     this.ctx.strokeStyle = this.color;
 
     const { bounds } = this.currentQuads.content[0];
@@ -478,18 +484,19 @@ class FlexboxHighlighter extends AutoRef
   renderFlexContainerBorder() {
     if (!this.currentQuads.content || !this.currentQuads.content[0]) {
       return;
     }
 
     const { devicePixelRatio } = this.win;
     const lineWidth = getDisplayPixelRatio(this.win) * 2;
     const offset = (lineWidth / 2) % 1;
-    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
-    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
+    const zoom = getCurrentZoom(this.win);
+    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio * zoom);
+    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio * zoom);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash);
     this.ctx.lineWidth = lineWidth;
     this.ctx.strokeStyle = this.color;
 
     const { bounds } = this.currentQuads.content[0];
@@ -502,18 +509,19 @@ class FlexboxHighlighter extends AutoRef
   renderFlexContainerFill() {
     if (!this.currentQuads.content || !this.currentQuads.content[0]) {
       return;
     }
 
     const { devicePixelRatio } = this.win;
     const lineWidth = getDisplayPixelRatio(this.win);
     const offset = (lineWidth / 2) % 1;
-    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
-    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
+    const zoom = getCurrentZoom(this.win);
+    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio * zoom);
+    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio * zoom);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash);
     this.ctx.lineWidth = 0;
     this.ctx.strokeStyle = this.color;
     this.ctx.fillStyle = this.getFlexContainerPattern(devicePixelRatio);
 
@@ -535,18 +543,19 @@ class FlexboxHighlighter extends AutoRef
   renderFlexItems() {
     if (!this.flexData || !this.currentQuads.content || !this.currentQuads.content[0]) {
       return;
     }
 
     const { devicePixelRatio } = this.win;
     const lineWidth = getDisplayPixelRatio(this.win);
     const offset = (lineWidth / 2) % 1;
-    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
-    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
+    const zoom = getCurrentZoom(this.win);
+    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio * zoom);
+    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio * zoom);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.item.lineDash);
     this.ctx.lineWidth = lineWidth;
     this.ctx.strokeStyle = this.color;
 
     const { bounds } = this.currentQuads.content[0];
@@ -555,20 +564,20 @@ class FlexboxHighlighter extends AutoRef
       for (const flexItem of flexLine.items) {
         const quads = flexItem.quads;
         if (!quads.length) {
           continue;
         }
 
         // Adjust the flex item bounds relative to the current quads.
         const { bounds: flexItemBounds } = quads[0];
-        const left = Math.round(flexItemBounds.left - bounds.left);
-        const top = Math.round(flexItemBounds.top - bounds.top);
-        const right = Math.round(flexItemBounds.right - bounds.left);
-        const bottom = Math.round(flexItemBounds.bottom - bounds.top);
+        const left = Math.round(flexItemBounds.left / zoom - bounds.left);
+        const top = Math.round(flexItemBounds.top / zoom - bounds.top);
+        const right = Math.round(flexItemBounds.right / zoom - bounds.left);
+        const bottom = Math.round(flexItemBounds.bottom / zoom - bounds.top);
 
         clearRect(this.ctx, left, top, right, bottom, this.currentMatrix);
         drawRect(this.ctx, left, top, right, bottom, this.currentMatrix);
         this.ctx.stroke();
       }
     }
 
     this.ctx.restore();
@@ -577,18 +586,19 @@ class FlexboxHighlighter extends AutoRef
   renderFlexLines() {
     if (!this.flexData || !this.currentQuads.content || !this.currentQuads.content[0]) {
       return;
     }
 
     const { devicePixelRatio } = this.win;
     const lineWidth = getDisplayPixelRatio(this.win);
     const offset = (lineWidth / 2) % 1;
-    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
-    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
+    const zoom = getCurrentZoom(this.win);
+    const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio * zoom);
+    const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio * zoom);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.lineWidth = lineWidth;
     this.ctx.strokeStyle = this.color;
 
     const { bounds } = this.currentQuads.content[0];
     const isColumn = this.flexDirection.startsWith("column");
@@ -635,35 +645,36 @@ class FlexboxHighlighter extends AutoRef
     this.ctx.restore();
   }
 
   renderJustifyContent() {
     if (!this.flexData || !this.currentQuads.content || !this.currentQuads.content[0]) {
       return;
     }
 
+    const zoom = getCurrentZoom(this.win);
     const { bounds } = this.currentQuads.content[0];
     const isColumn = this.flexDirection.startsWith("column");
 
     for (const flexLine of this.flexData.lines) {
       const { crossStart, crossSize } = flexLine;
       let mainStart = 0;
 
       for (const flexItem of flexLine.items) {
         const quads = flexItem.quads;
         if (!quads.length) {
           continue;
         }
 
         // Adjust the flex item bounds relative to the current quads.
         const { bounds: flexItemBounds } = quads[0];
-        const left = Math.round(flexItemBounds.left - bounds.left);
-        const top = Math.round(flexItemBounds.top - bounds.top);
-        const right = Math.round(flexItemBounds.right - bounds.left);
-        const bottom = Math.round(flexItemBounds.bottom - bounds.top);
+        const left = Math.round(flexItemBounds.left / zoom - bounds.left);
+        const top = Math.round(flexItemBounds.top / zoom - bounds.top);
+        const right = Math.round(flexItemBounds.right / zoom - bounds.left);
+        const bottom = Math.round(flexItemBounds.bottom / zoom - bounds.top);
 
         if (isColumn) {
           this.drawJustifyContent(crossStart, mainStart, crossStart + crossSize, top);
           mainStart = bottom;
         } else {
           this.drawJustifyContent(mainStart, crossStart, left, crossStart + crossSize);
           mainStart = right;
         }
--- a/devtools/shared/layout/utils.js
+++ b/devtools/shared/layout/utils.js
@@ -188,35 +188,37 @@ exports.getFrameOffsets = getFrameOffset
  *        The window where to stop to iterate. If `null` is given, the top
  *        window is used.
  * @param {DOMNode} node
  *        The node for which we are to get the box model region
  *        quads.
  * @param {String} region
  *        The box model region to return: "content", "padding", "border" or
  *        "margin".
+ * @param {Object} [options.ignoreZoom=false]
+ *        Ignore zoom used in the context of e.g. canvas.
  * @return {Array}
  *        An array of objects that have the same structure as quads returned by
  *        getBoxQuads. An empty array if the node has no quads or is invalid.
  */
-function getAdjustedQuads(boundaryWindow, node, region) {
+function getAdjustedQuads(boundaryWindow, node, region, {ignoreZoom} = {}) {
   if (!node || !node.getBoxQuads) {
     return [];
   }
 
   const quads = node.getBoxQuads({
     box: region,
     relativeTo: boundaryWindow.document
   });
 
   if (!quads.length) {
     return [];
   }
 
-  const scale = getCurrentZoom(node);
+  const scale = ignoreZoom ? 1 : getCurrentZoom(node);
   const { scrollX, scrollY } = boundaryWindow;
 
   const xOffset = scrollX * scale;
   const yOffset = scrollY * scale;
 
   const adjustedQuads = [];
   for (const quad of quads) {
     const bounds = quad.getBounds();