Title: [225495] trunk
Revision
225495
Author
commit-qu...@webkit.org
Date
2017-12-04 14:49:25 -0800 (Mon, 04 Dec 2017)

Log Message

<video> and scale() transforms yield shrunk small or clipped controls
https://bugs.webkit.org/show_bug.cgi?id=180358
<rdar://problem/34436124>

Patch by Antoine Quint <grao...@apple.com> on 2017-12-04
Reviewed by Dean Jackson.

Source/WebCore:

To compute the bounds of the media controls, we would call getBoundingClientRect()
on the root-most element in the shadow root, which is styled to have width and height
set to 100%, which allows to match the metrics of the host media element, without
the borders.

However, if the host media element has CSS transforms applied, these would be factored
into calls to getBoundingClientRect() and the controls would be too large and clipped,
in case the scale was more than 1, or shrunk, in case the scale was less than 1.

To obtain correct metrics, we computed the complete transformation matrix applied to
the host media element, and apply its inverted matrix to each corner point of the
bounds returned for the root-most container element in the shadow root.

Then we compute the width and height of this transformed rectangle and set those to
be our media controls' metrics.

Test: media/modern-media-controls/css/transformed-media.html

* Modules/modern-media-controls/media/media-controller.js:
(MediaController.prototype._updateControlsSize):
(MediaController.prototype._controlsWidth): Deleted.

LayoutTests:

Write a new test that ensures that we reflect the width and height, not accounting
for borders, of the host media element when sizing media controls.

* media/modern-media-controls/css/transformed-media-expected.txt: Added.
* media/modern-media-controls/css/transformed-media.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (225494 => 225495)


--- trunk/LayoutTests/ChangeLog	2017-12-04 22:47:04 UTC (rev 225494)
+++ trunk/LayoutTests/ChangeLog	2017-12-04 22:49:25 UTC (rev 225495)
@@ -1,5 +1,19 @@
 2017-12-04  Antoine Quint  <grao...@apple.com>
 
+        <video> and scale() transforms yield shrunk small or clipped controls
+        https://bugs.webkit.org/show_bug.cgi?id=180358
+        <rdar://problem/34436124>
+
+        Reviewed by Dean Jackson.
+
+        Write a new test that ensures that we reflect the width and height, not accounting
+        for borders, of the host media element when sizing media controls.
+
+        * media/modern-media-controls/css/transformed-media-expected.txt: Added.
+        * media/modern-media-controls/css/transformed-media.html: Added.
+
+2017-12-04  Antoine Quint  <grao...@apple.com>
+
         Cursor is not visible after exiting full screen video
         https://bugs.webkit.org/show_bug.cgi?id=180247
         <rdar://problem/33885922>

Added: trunk/LayoutTests/media/modern-media-controls/css/transformed-media-expected.txt (0 => 225495)


--- trunk/LayoutTests/media/modern-media-controls/css/transformed-media-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/css/transformed-media-expected.txt	2017-12-04 22:49:25 UTC (rev 225495)
@@ -0,0 +1,6 @@
+PASS mediaControls.style.width is "560px"
+PASS mediaControls.style.height is "260px"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/media/modern-media-controls/css/transformed-media.html (0 => 225495)


--- trunk/LayoutTests/media/modern-media-controls/css/transformed-media.html	                        (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/css/transformed-media.html	2017-12-04 22:49:25 UTC (rev 225495)
@@ -0,0 +1,39 @@
+<head>
+    <meta name="viewport" content="user-scalable=no, width=device-width">
+    <style type="text/css" media="screen">
+        
+        * {
+            transform-origin: top left;
+        }
+
+        div {
+            transform: scale(0.75);
+        }
+
+        video {
+            width: 600px;
+            height: 300px;
+            border: 20px solid blue;
+            box-sizing: border-box;
+            background-color: red;
+            transform: scale(0.5);
+        }
+        
+    </style>
+</head>
+<body>
+    <div>
+        <video controls autoplay></video>
+    </div>
+    <script src=""
+    <script type="text/_javascript_">
+
+        const media = document.querySelector("video");
+        const shadowRoot = window.internals.shadowRoot(media);
+        const mediaControls = shadowRoot.querySelector(".media-controls");
+        shouldBeEqualToString("mediaControls.style.width", "560px"); // width - (2 * border)
+        shouldBeEqualToString("mediaControls.style.height", "260px"); // height - (2 * border)
+        
+    </script>
+    <script src=""
+</body>

Modified: trunk/Source/WebCore/ChangeLog (225494 => 225495)


--- trunk/Source/WebCore/ChangeLog	2017-12-04 22:47:04 UTC (rev 225494)
+++ trunk/Source/WebCore/ChangeLog	2017-12-04 22:49:25 UTC (rev 225495)
@@ -1,5 +1,35 @@
 2017-12-04  Antoine Quint  <grao...@apple.com>
 
+        <video> and scale() transforms yield shrunk small or clipped controls
+        https://bugs.webkit.org/show_bug.cgi?id=180358
+        <rdar://problem/34436124>
+
+        Reviewed by Dean Jackson.
+
+        To compute the bounds of the media controls, we would call getBoundingClientRect()
+        on the root-most element in the shadow root, which is styled to have width and height
+        set to 100%, which allows to match the metrics of the host media element, without
+        the borders.
+
+        However, if the host media element has CSS transforms applied, these would be factored
+        into calls to getBoundingClientRect() and the controls would be too large and clipped,
+        in case the scale was more than 1, or shrunk, in case the scale was less than 1.
+
+        To obtain correct metrics, we computed the complete transformation matrix applied to
+        the host media element, and apply its inverted matrix to each corner point of the
+        bounds returned for the root-most container element in the shadow root.
+
+        Then we compute the width and height of this transformed rectangle and set those to
+        be our media controls' metrics.
+
+        Test: media/modern-media-controls/css/transformed-media.html
+
+        * Modules/modern-media-controls/media/media-controller.js:
+        (MediaController.prototype._updateControlsSize):
+        (MediaController.prototype._controlsWidth): Deleted.
+
+2017-12-04  Antoine Quint  <grao...@apple.com>
+
         Cursor is not visible after exiting full screen video
         https://bugs.webkit.org/show_bug.cgi?id=180247
         <rdar://problem/33885922>

Modified: trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js (225494 => 225495)


--- trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js	2017-12-04 22:47:04 UTC (rev 225494)
+++ trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js	2017-12-04 22:49:25 UTC (rev 225495)
@@ -212,16 +212,53 @@
 
     _updateControlsSize()
     {
-        this.controls.width = this._controlsWidth();
-        this.controls.height = Math.round(this.container.getBoundingClientRect().height * this.controls.scaleFactor);
+        // To compute the bounds of the controls, we need to account for the computed transform applied
+        // to the media element, and apply the inverted transform to the bounds computed on the container
+        // element in the shadow root, which is naturally sized to match the metrics of its host,
+        // excluding borders.
+
+        // First, we traverse the node hierarchy up from the media element to compute the effective
+        // transform matrix applied to the media element.
+        let node = this.media;
+        let transform = new WebKitCSSMatrix;
+        while (node && node instanceof HTMLElement) {
+            transform = transform.multiply(new WebKitCSSMatrix(getComputedStyle(node).transform));
+            node = node.parentNode;
+        }
+
+        // Then, we take each corner of the container element in the shadow root and transform
+        // each with the inverted matrix we just computed so that we can compute the untransformed
+        // bounds of the media element.
+        const bounds = this.container.getBoundingClientRect();
+        const invertedTransform = transform.inverse();
+        let minX = Infinity;
+        let minY = Infinity;
+        let maxX = -Infinity;
+        let maxY = -Infinity;
+        [
+            new DOMPoint(bounds.left, bounds.top),
+            new DOMPoint(bounds.right, bounds.top),
+            new DOMPoint(bounds.right, bounds.bottom),
+            new DOMPoint(bounds.left, bounds.bottom)
+        ].forEach(corner => {
+            const point = corner.matrixTransform(invertedTransform);
+            if (point.x < minX)
+                minX = point.x;
+            if (point.x > maxX)
+                maxX = point.x;
+            if (point.y < minY)
+                minY = point.y;
+            if (point.y > maxY)
+                maxY = point.y;
+        });
+
+        // Finally, we factor in the scale factor of the controls themselves, which reflects the page's scale factor.
+        this.controls.width = Math.round((maxX - minX) * this.controls.scaleFactor);
+        this.controls.height = Math.round((maxY - minY) * this.controls.scaleFactor);
+
         this.controls.shouldCenterControlsVertically = this.isAudio;
     }
 
-    _controlsWidth()
-    {
-        return Math.round(this.container.getBoundingClientRect().width * (this.controls ? this.controls.scaleFactor : 1));
-    }
-
     _returnMediaLayerToInlineIfNeeded()
     {
         if (this.host)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to