Bug 1370278 - used getTransformToAncestor in Grid Inspector highlighter; r=gl
authorMatteo Ferretti <mferretti@mozilla.com>
Fri, 09 Jun 2017 01:31:08 +0200
changeset 411264 908eeb65a000fbe12ddb8f48cec00872451ebccb
parent 411263 3fea90e94f1df641f540a3b62e42e171f9b9ee39
child 411265 ee6c97bf9ca68e449662d9bba14ec83dc19753ba
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl
bugs1370278
milestone55.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 1370278 - used getTransformToAncestor in Grid Inspector highlighter; r=gl Used the new chrome-only API to obtain the transformation matrix of the current node, relative to the inspected window's root element. That also includes all the transformations from the element's ancestor; plus the method is more robust and we can simplify the current code, removing also some hack. Deleted also the test for dom_matrix_2d, since one of the method was testing now doesn't exist anymore, and the second it's just a map to native method that has its own tests on platform. MozReview-Commit-ID: 35rs34RSMYA
devtools/server/actors/highlighters/css-grid.js
devtools/shared/layout/dom-matrix-2d.js
devtools/shared/tests/mochitest/chrome.ini
devtools/shared/tests/mochitest/test_dom_matrix_2d.html
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -12,27 +12,26 @@ const {
   createNode,
   createSVGNode,
   moveInfobar,
 } = require("./utils/markup");
 const {
   getCurrentZoom,
   getDisplayPixelRatio,
   setIgnoreLayoutChanges,
-  getNodeBounds,
   getViewportDimensions,
 } = require("devtools/shared/layout/utils");
 const {
   identity,
   apply,
   translate,
   multiply,
   scale,
+  isIdentity,
   getNodeTransformationMatrix,
-  getNodeTransformOrigin
 } = require("devtools/shared/layout/dom-matrix-2d");
 const { stringifyGridFragments } = require("devtools/server/actors/utils/css-grid-utils");
 const { LocalizationHelper } = require("devtools/shared/l10n");
 
 const LAYOUT_STRINGS_URI = "devtools/client/locales/layout.properties";
 const LAYOUT_L10N = new LocalizationHelper(LAYOUT_STRINGS_URI);
 
 const CSS_GRID_ENABLED_PREF = "layout.css.grid.enabled";
@@ -1042,51 +1041,41 @@ CssGridHighlighter.prototype = extend(Au
    *   5. Any CSS transformation applied directly to the element (only 2D
    *      transformation; the 3D transformation are flattened, see `dom-matrix-2d` module
    *      for further details.)
    *
    *  The transformations of the element's ancestors are not currently computed (see
    *  bug 1355675).
    */
   updateCurrentMatrix() {
-    let origin = getNodeTransformOrigin(this.currentNode);
-    let bounds = getNodeBounds(this.win, this.currentNode);
-    let nodeMatrix = getNodeTransformationMatrix(this.currentNode);
     let computedStyle = this.currentNode.ownerGlobal.getComputedStyle(this.currentNode);
 
     let paddingTop = parseFloat(computedStyle.paddingTop);
     let paddingLeft = parseFloat(computedStyle.paddingLeft);
     let borderTop = parseFloat(computedStyle.borderTopWidth);
     let borderLeft = parseFloat(computedStyle.borderLeftWidth);
 
-    // Subtract padding and border values to compensate for top/left being moved by
-    // padding and / or borders.
-    let ox = origin[0] - paddingLeft - borderLeft;
-    let oy = origin[1] - paddingTop - borderTop;
+    let nodeMatrix = getNodeTransformationMatrix(this.currentNode,
+      this.win.document.documentElement);
 
     let m = identity();
 
-    // First, we scale based on the display's current pixel ratio.
-    m = multiply(m, scale(getDisplayPixelRatio(this.win)));
-    // Then we translate the origin to the node's top left corner.
-    m = multiply(m, translate(bounds.p1.x, bounds.p1.y));
-    // And scale based on the current zoom factor.
-    m = multiply(m, scale(getCurrentZoom(this.win)));
-    // Then translate the origin based on the node's padding and border values.
+    // First, we scale based on the device pixel ratio.
+    m = multiply(m, scale(this.win.devicePixelRatio));
+    // Then, we apply the current node's transformation matrix, relative to the
+    // inspected window's root element, but only if it's not a identity matrix.
+    if (isIdentity(nodeMatrix)) {
+      this.hasNodeTransformations = false;
+    } else {
+      m = multiply(m, nodeMatrix);
+      this.hasNodeTransformations = true;
+    }
+
+    // Finally, we translate the origin based on the node's padding and border values.
     m = multiply(m, translate(paddingLeft + borderLeft, paddingTop + borderTop));
-    // Finally, we can apply the current node's transformation matrix, taking in account
-    // the `transform-origin` property and the node's top and left padding.
-    if (nodeMatrix) {
-      m = multiply(m, translate(ox, oy));
-      m = multiply(m, nodeMatrix);
-      m = multiply(m, translate(-ox, -oy));
-      this.hasNodeTransformations = true;
-    } else {
-      this.hasNodeTransformations = false;
-    }
 
     this.currentMatrix = m;
   },
 
   getFirstRowLinePos(fragment) {
     return fragment.rows.lines[0].start;
   },
 
--- a/devtools/shared/layout/dom-matrix-2d.js
+++ b/devtools/shared/layout/dom-matrix-2d.js
@@ -100,59 +100,44 @@ exports.multiply = multiply;
  */
 const apply = (M, P) => [
   M[0] * P[0] + M[1] * P[1] + M[2],
   M[3] * P[0] + M[4] * P[1] + M[5],
 ];
 exports.apply = apply;
 
 /**
- * Returns the transformation origin point for the given node.
+ * Returns `true` if the given matrix is a identity matrix.
  *
- * @param {DOMNode} node
- *        The node.
- * @return {Array}
- *        The transformation origin point.
+ * @param {Array} M
+ *        The matrix to check
+ * @return {Boolean}
+ *        `true` if the matrix passed is a identity matrix, `false` otherwise.
  */
-function getNodeTransformOrigin(node) {
-  let origin = node.ownerGlobal.getComputedStyle(node).transformOrigin;
-
-  return origin.split(/ /).map(parseFloat);
-}
-exports.getNodeTransformOrigin = getNodeTransformOrigin;
+const isIdentity = (M) =>
+  M[0] === 1 && M[1] === 0 && M[2] === 0 &&
+  M[3] === 0 && M[4] === 1 && M[5] === 0 &&
+  M[6] === 0 && M[7] === 0 && M[8] === 1;
+exports.isIdentity = isIdentity;
 
 /**
- * Returns the transformation matrix for the given node.
+ * Returns the transformation matrix for the given node, relative to the ancestor passed
+ * as second argument.
+ * If no ancestor is specified, it will returns the transformation matrix relative to the
+ * node's parent element.
  *
  * @param {DOMNode} node
  *        The node.
- * @return {Array}
+ * @param {DOMNode} ancestor
+ *        The ancestor of the node given.
+ ** @return {Array}
  *        The transformation matrix.
  */
-function getNodeTransformationMatrix(node) {
-  let t = node.ownerGlobal.getComputedStyle(node).transform;
-
-  if (t === "none") {
-    return null;
-  }
-
-  // We're assuming is a 2d matrix.
-  let m = t.substring(t.indexOf("(") + 1, t.length - 1).split(/,\s*/).map(Number);
-  let [a, b, c, d, e, f] = m;
-
-  // If the length is 16, it's a 3d matrix: in that case we'll extrapolate only the values
-  // we need for the 2D transformation; this cover the scenario where 3D CSS properties
-  // are used only for HW acceleration on 2D transformation.
-  if (m.length === 16) {
-    c = m[4];
-    d = m[5];
-    e = m[12];
-    f = m[13];
-  }
+function getNodeTransformationMatrix(node, ancestor = node.parentElement) {
+  let { a, b, c, d, e, f } = node.getTransformToAncestor(ancestor);
 
   return [
     a, c, e,
     b, d, f,
     0, 0, 1
   ];
 }
-
 exports.getNodeTransformationMatrix = getNodeTransformationMatrix;
--- a/devtools/shared/tests/mochitest/chrome.ini
+++ b/devtools/shared/tests/mochitest/chrome.ini
@@ -1,8 +1,7 @@
 [DEFAULT]
 tags = devtools
 skip-if = os == 'android'
 
 [test_css-logic-getCssPath.html]
-[test_dom_matrix_2d.html]
 [test_eventemitter_basic.html]
 skip-if = os == 'linux' && debug # Bug 1205739
deleted file mode 100644
--- a/devtools/shared/tests/mochitest/test_dom_matrix_2d.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE html>
-<!--
-  Any copyright is dedicated to the Public Domain.
-  http://creativecommons.org/publicdomain/zero/1.0/
--->
-
-<html>
-  <!--
-  https://bugzilla.mozilla.org/show_bug.cgi?id=1297072
-  -->
-  <head>
-    <meta charset="utf8">
-    <title>Testing 2d matrix utility functions for DOM</title>
-
-    <script type="application/javascript"
-            src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-    <link rel="stylesheet" type="text/css"
-          href="chrome://mochikit/content/tests/SimpleTest/test.css">
-    <style>
-      #element {
-        position: absolute;
-        top: 20px;
-        left: 10px;
-        width: 320px;
-        height: 200px;
-        background: salmon;
-      }
-    </style>
-  </head>
-
-  <body>
-    <div id="element"></div>
-
-    <script type="application/javascript">
-      "use strict";
-
-      const { utils: Cu } = Components;
-      const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
-      const {
-        getNodeTransformationMatrix,
-        getNodeTransformOrigin
-      } = require("devtools/shared/layout/dom-matrix-2d");
-
-      let element = document.getElementById("element");
-
-      testNodeTransformOrigin(element);
-      testNodeTransformationMatrix(element);
-
-      function testNodeTransformOrigin(node) {
-        isDeeply(getNodeTransformOrigin(node), [160, 100],
-          "Default Transform Origin is correct.");
-
-        node.style.transformOrigin = "left 10%";
-        isDeeply(getNodeTransformOrigin(node), [0, 20],
-          "Transform Origin is properly computed.");
-
-        node.style.transformOrigin = "invalid";
-        isDeeply(getNodeTransformOrigin(node), [0, 20],
-          "Invalid values are ignored.");
-
-        node.style.transformOrigin = "left 5px -3px";
-        isDeeply(getNodeTransformOrigin(node), [0, 5, -3],
-          "3D coordinates and negative numbers are properly computed.");
-      }
-
-      function testNodeTransformationMatrix(node) {
-        is(getNodeTransformationMatrix(node), null,
-          "Default Transformation Matrix is `null`");
-
-        node.style.transform = "translate(10%, 20px)";
-        isDeeply(getNodeTransformationMatrix(node), [ 1, 0, 32, 0, 1, 20, 0, 0, 1 ],
-          "Transformation Matrix properly computed with translation.");
-
-        node.style.transform = "translate(10%, 20px) scale(2)";
-        isDeeply(getNodeTransformationMatrix(node), [ 2, 0, 32, 0, 2, 20, 0, 0, 1 ],
-          "Transformation Matrix properly translated and scaled.");
-
-        node.style.transform = "scale(2) translate(10%, 20px)";
-        isDeeply(getNodeTransformationMatrix(node), [ 2, 0, 64, 0, 2, 40, 0, 0, 1 ],
-          "Transformation Matrix properly scaled and translated.");
-
-        node.style.transform = "translate3d(12px, 50%, 3em)";
-        isDeeply(getNodeTransformationMatrix(node), [ 1, 0, 12, 0, 1, 100, 0, 0, 1 ],
-          "3D Transformation Matrix are handled for 2D values.");
-      }
-    </script>
-  </body>
-</html>