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 499223 7a275e7abf9b88e0d70a14e5a3dea3a7a8ce21e0
parent 499222 8878ac1f9f36c00d902b7a5d4e636ffbbc9217de
child 499224 122ac3c6e1dc29aeb824845419658dfd6c45604a
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl
bugs1478481
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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();