Title: [286743] trunk
Revision
286743
Author
jer.no...@apple.com
Date
2021-12-08 14:59:49 -0800 (Wed, 08 Dec 2021)

Log Message

[VTT] Fix various issues with complicated rendering of VTT cues
https://bugs.webkit.org/show_bug.cgi?id=233901

Reviewed by Eric Carlson.

Source/WebCore:

Tests: media/track/track-webvtt-no-snap-to-lines-overlap.html
       media/track/track-webvtt-snap-to-lines-inline-style.html
       media/track/track-webvtt-snap-to-lines-left-right.html

When positioning VTT cues, the spec requires UAs to avoid collisions between cues
by detecting that two cues overlap each other. However, WebKit's implementation
looks for collisions between non-displaying portions of the cues; namely the
::-webkit-media-text-track-display element, which is used to position the displaying
portion of the cue. Instead, the UA should look for collisions between the
::-webkit-media-text-track-display-backdrop element, which holds the background
of the cue, if present.

Add a convenience function to retrieve the backdrop element, and another to retrieve
the cue itself.

Add cast macros for RenderVTTCue to allow downcast<>ing. Use this macro to retrieve
other cues's backdrop elements for collision avoidance.

VTTCueBox::applyCSSProperties() had a section for moving cues into place that is entirely
unneeded if VTTCue::getCSSPosition() returns the pre-calculated m_displayPosition.

RenderVTTCue::initializeLayoutParameters() is a careful implementation of the specification,
accurately layout out cues' initial position so that the text run is exactly at the
bottom of the content box. However, if the cue has a border, padding, or extra height,
this will result in the cue being pushed outside the content box. To account for this,
adjust the inital layout parameter by the difference between the cue text size and the
backdrop element size.

RenderVTTCue::layout() will create a LayoutStateMaintainer, which modifies the behavior of
layout machinery during the layout itself. However, certain child renderers get dramatically
incorrect results for absoluteBoundingRect() unless the maintainer explicitly sets disableState.

* html/track/VTTCue.cpp:
(WebCore::VTTCueBox::applyCSSProperties):
(WebCore::VTTCue::getCSSPosition const):
* html/track/VTTCue.h:
* rendering/RenderObject.h:
(WebCore::RenderObject::isRenderVTTCue const):
* rendering/RenderVTTCue.cpp:
(WebCore::RenderVTTCue::layout):
(WebCore::RenderVTTCue::initializeLayoutParameters):
(WebCore::RenderVTTCue::isOutside const):
(WebCore::RenderVTTCue::overlappingObject const):
(WebCore::RenderVTTCue::overlappingObjectForRect const):
(WebCore::RenderVTTCue::moveIfNecessaryToKeepWithinContainer):
(WebCore::RenderVTTCue::findNonOverlappingPosition const):
(WebCore::RenderVTTCue::repositionGenericCue):
(WebCore::RenderVTTCue::backdropBox const):
(WebCore::RenderVTTCue::cueBox const):

LayoutTests:

* media/track/captions-webvtt/no-snap-to-lines-overlap.vtt: Added.
* media/track/captions-webvtt/snap-to-lines-inline-style.vtt: Added.
* media/track/captions-webvtt/snap-to-lines-left-and-right.vtt: Added.
* media/track/track-webvtt-no-snap-to-lines-overlap-expected.html: Added.
* media/track/track-webvtt-no-snap-to-lines-overlap.html: Added.
* media/track/track-webvtt-snap-to-lines-inline-style-expected.html: Added.
* media/track/track-webvtt-snap-to-lines-inline-style.html: Added.
* media/track/track-webvtt-snap-to-lines-left-right-expected.html: Added.
* media/track/track-webvtt-snap-to-lines-left-right.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (286742 => 286743)


--- trunk/LayoutTests/ChangeLog	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/LayoutTests/ChangeLog	2021-12-08 22:59:49 UTC (rev 286743)
@@ -1,3 +1,20 @@
+2021-12-08  Jer Noble  <jer.no...@apple.com>
+
+        [VTT] Fix various issues with complicated rendering of VTT cues
+        https://bugs.webkit.org/show_bug.cgi?id=233901
+
+        Reviewed by Eric Carlson.
+
+        * media/track/captions-webvtt/no-snap-to-lines-overlap.vtt: Added.
+        * media/track/captions-webvtt/snap-to-lines-inline-style.vtt: Added.
+        * media/track/captions-webvtt/snap-to-lines-left-and-right.vtt: Added.
+        * media/track/track-webvtt-no-snap-to-lines-overlap-expected.html: Added.
+        * media/track/track-webvtt-no-snap-to-lines-overlap.html: Added.
+        * media/track/track-webvtt-snap-to-lines-inline-style-expected.html: Added.
+        * media/track/track-webvtt-snap-to-lines-inline-style.html: Added.
+        * media/track/track-webvtt-snap-to-lines-left-right-expected.html: Added.
+        * media/track/track-webvtt-snap-to-lines-left-right.html: Added.
+
 2021-12-08  Rob Buis  <rb...@igalia.com>
 
         [css-contain] Prevent various kinds of propagation to RenderView

Added: trunk/LayoutTests/media/track/captions-webvtt/no-snap-to-lines-overlap.vtt (0 => 286743)


--- trunk/LayoutTests/media/track/captions-webvtt/no-snap-to-lines-overlap.vtt	                        (rev 0)
+++ trunk/LayoutTests/media/track/captions-webvtt/no-snap-to-lines-overlap.vtt	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,33 @@
+WEBVTT
+
+1
+00:00:00.000 --> 00:00:00.500 align:left line:0%
+Left
+
+2
+00:00:00.000 --> 00:00:00.500 align:right line:0%
+Right
+
+3
+00:00:00.000 --> 00:00:00.500 align:left line:0%
+Below
+
+4
+00:00:00.000 --> 00:00:00.500 align:right line:0%
+Below
+
+1
+00:00:00.000 --> 00:00:00.500 align:left line:100%
+Left
+
+2
+00:00:00.000 --> 00:00:00.500 align:right line:100%
+Right
+
+3
+00:00:00.000 --> 00:00:00.500 align:left line:100%
+Above
+
+4
+00:00:00.000 --> 00:00:00.500 align:right line:100%
+Above

Added: trunk/LayoutTests/media/track/captions-webvtt/snap-to-lines-inline-style.vtt (0 => 286743)


--- trunk/LayoutTests/media/track/captions-webvtt/snap-to-lines-inline-style.vtt	                        (rev 0)
+++ trunk/LayoutTests/media/track/captions-webvtt/snap-to-lines-inline-style.vtt	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,20 @@
+WEBVTT
+
+STYLE
+::cue(.doubleHeight) { font-size: 200%; background-color: black }
+
+1
+00:00:00.000 --> 00:00:00.500 align:left
+<c.doubleHeight>Left</c>
+
+2
+00:00:00.000 --> 00:00:00.500 align:right position:100%
+<c.doubleHeight>Right</c>
+
+3
+00:00:00.000 --> 00:00:00.500 align:left
+<c.doubleHeight>Above</c>
+
+4
+00:00:00.000 --> 00:00:00.500 align:right position:100%
+<c.doubleHeight>Above</c>

Added: trunk/LayoutTests/media/track/captions-webvtt/snap-to-lines-left-and-right.vtt (0 => 286743)


--- trunk/LayoutTests/media/track/captions-webvtt/snap-to-lines-left-and-right.vtt	                        (rev 0)
+++ trunk/LayoutTests/media/track/captions-webvtt/snap-to-lines-left-and-right.vtt	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,17 @@
+WEBVTT
+
+1
+00:00:00.000 --> 00:00:00.500 align:left
+Left
+
+2
+00:00:00.000 --> 00:00:00.500 align:right position:100%
+Right
+
+3
+00:00:00.000 --> 00:00:00.500 align:left
+Above
+
+4
+00:00:00.000 --> 00:00:00.500 align:right position:100%
+Above

Added: trunk/LayoutTests/media/track/track-webvtt-no-snap-to-lines-overlap-expected.html (0 => 286743)


--- trunk/LayoutTests/media/track/track-webvtt-no-snap-to-lines-overlap-expected.html	                        (rev 0)
+++ trunk/LayoutTests/media/track/track-webvtt-no-snap-to-lines-overlap-expected.html	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>track-webvtt-no-snap-to-lines-overlap</title>
+    <style>
+        .video { 
+            display: inline-block;
+            position: relative;
+            width: 320px;
+            height: 240px;
+        }
+        html { overflow:hidden }
+        body { margin:0 }
+        .cue-box {
+            position: absolute;
+            font-size: 12px;
+        }
+        .cue {
+            font-family: Ahem, sans-serif;
+            background-color: black;
+            color: green;
+        }
+    </style>
+    <script>var requirePixelDump = true;</script>
+    <script src=""
+    <script src=""
+    <script>
+    window.addEventListener('load', async event => {
+        consoleWrite('RUN(video.querySelector("track").src = ""
+        consoleWrite('RUN(video.textTracks[0].mode = "showing")');
+        consoleWrite('EVENT(load)');
+        consoleWrite('RUN(video.src = "" "w3c/track/webvtt/media/white"))');
+        consoleWrite('EVENT(canplaythrough)');
+        endTest();
+    });
+    </script>
+</head>
+<body>
+    <div class="video">
+        <div class="cue-box" style="left:0; top:0; text-align: left;">
+            <span class="cue">Left</span><br>
+            <span class="cue">Below</span>
+        </div>
+        <div class="cue-box" style="right:0; top:0; text-align: right">
+            <span class="cue">Right</span><br>
+            <span class="cue">Below</span>
+        </div>
+        <div class="cue-box" style="left:0; bottom:0; text-align: left">
+            <span class="cue">Above</span><br>
+            <span class="cue">Left</span>
+        </div>
+        <div class="cue-box" style="right:0; bottom:0; text-align: right">
+            <span class="cue">Above</span><br>
+            <span class="cue">Right</span>
+        </div>
+    </div>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/track/track-webvtt-no-snap-to-lines-overlap.html (0 => 286743)


--- trunk/LayoutTests/media/track/track-webvtt-no-snap-to-lines-overlap.html	                        (rev 0)
+++ trunk/LayoutTests/media/track/track-webvtt-no-snap-to-lines-overlap.html	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>track-webvtt-no-snap-to-lines-overlap</title>
+    <style>
+        html { overflow:hidden }
+        body { margin:0 }
+        ::cue {
+            font-family: Ahem, sans-serif;
+            font-size: 12px;
+            background-color: black;
+            color: green;
+        }
+    </style>
+    <script>var requirePixelDump = true;</script>
+    <script src=""
+    <script src=""
+    <script>
+    window.addEventListener('load', async event => {
+        findMediaElement();
+
+        run(`video.querySelector("track").src = ""
+        run(`video.textTracks[0].mode = "showing"`);
+        await waitFor(video.querySelector('track'), 'load');
+
+        run(`video.src = "" "w3c/track/webvtt/media/white")`);
+        await waitFor(video, 'canplaythrough');
+
+        endTest();
+    });
+    </script>
+</head>
+<body>
+    <video>
+        <track id="testTrack" kind="captions" default>
+    </video>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-inline-style-expected.html (0 => 286743)


--- trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-inline-style-expected.html	                        (rev 0)
+++ trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-inline-style-expected.html	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>track-webvtt-snap-to-lines-inline-style</title>
+    <style>
+        .video { 
+            display: inline-block;
+            position: relative;
+            width: 320px;
+            height: 240px;
+        }
+        html { overflow:hidden }
+        body { margin:0 }
+        .cue-box {
+            position: absolute;
+        }
+        .cue {
+            font-family: Ahem, sans-serif;
+            background-color: black;
+            color: green;
+            font-size: 24px;
+        }
+    </style>
+    <script>var requirePixelDump = true;</script>
+    <script src=""
+    <script src=""
+    <script>
+    window.addEventListener('load', async event => {
+        consoleWrite('RUN(video.querySelector("track").src = ""
+        consoleWrite('RUN(video.textTracks[0].mode = "showing")');
+        consoleWrite('EVENT(load)');
+        consoleWrite('RUN(video.src = "" "w3c/track/webvtt/media/white"))');
+        consoleWrite('EVENT(canplaythrough)');
+        endTest();
+    });
+    </script>
+</head>
+<body>
+    <div class="video">
+        <div class="cue-box" style="left:0; bottom:0; text-align: left">
+            <span class="cue">Above</span><br>
+            <span class="cue">Left</span>
+        </div>
+        <div class="cue-box" style="right:0; bottom:0; text-align: right">
+            <span class="cue">Above</span><br>
+            <span class="cue">Right</span>
+        </div>
+    </div>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-inline-style.html (0 => 286743)


--- trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-inline-style.html	                        (rev 0)
+++ trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-inline-style.html	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>track-webvtt-snap-to-lines-inline-style</title>
+    <style>
+        html { overflow:hidden }
+        body { margin:0 }
+        ::cue {
+            font-family: Ahem, sans-serif;
+            font-size: 12px;
+            background-color: black;
+            color: green;
+        }
+    </style>
+    <script>var requirePixelDump = true;</script>
+    <script src=""
+    <script src=""
+    <script>
+    window.addEventListener('load', async event => {
+        findMediaElement();
+
+        run(`video.querySelector("track").src = ""
+        run(`video.textTracks[0].mode = "showing"`);
+        await waitFor(video.querySelector('track'), 'load');
+
+        run(`video.src = "" "w3c/track/webvtt/media/white")`);
+        await waitFor(video, 'canplaythrough');
+
+        endTest();
+    });
+    </script>
+</head>
+<body>
+    <video>
+        <track id="testTrack" src="" kind="captions" default>
+    </video>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-left-right-expected.html (0 => 286743)


--- trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-left-right-expected.html	                        (rev 0)
+++ trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-left-right-expected.html	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>track-webvtt-snap-to-lines-left-right</title>
+    <style>
+        .video { 
+            display: inline-block;
+            position: relative;
+            width: 320px;
+            height: 240px;
+        }
+        html { overflow:hidden }
+        body { margin:0 }
+        .cue-box {
+            position: absolute;
+            font-size: 12px;
+        }
+        .cue {
+            font-family: Ahem, sans-serif;
+            background-color: black;
+            color: green;
+        }
+    </style>
+    <script>var requirePixelDump = true;</script>
+    <script src=""
+    <script src=""
+    <script>
+    window.addEventListener('load', async event => {
+        consoleWrite('RUN(video.querySelector("track").src = ""
+        consoleWrite('RUN(video.textTracks[0].mode = "showing")');
+        consoleWrite('EVENT(load)');
+        consoleWrite('RUN(video.src = "" "w3c/track/webvtt/media/white"))');
+        consoleWrite('EVENT(canplaythrough)');
+        endTest();
+    });
+    </script>
+</head>
+<body>
+    <div class="video">
+        <div class="cue-box" style="left:0; bottom:0; text-align: left">
+            <span class="cue">Above</span><br>
+            <span class="cue">Left</span>
+        </div>
+        <div class="cue-box" style="right:0; bottom:0; text-align: right">
+            <span class="cue">Above</span><br>
+            <span class="cue">Right</span>
+        </div>
+    </div>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-left-right.html (0 => 286743)


--- trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-left-right.html	                        (rev 0)
+++ trunk/LayoutTests/media/track/track-webvtt-snap-to-lines-left-right.html	2021-12-08 22:59:49 UTC (rev 286743)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>track-webvtt-snap-to-lines-left-right</title>
+    <style>
+        html { overflow:hidden }
+        body { margin:0 }
+        ::cue {
+            font-family: Ahem, sans-serif;
+            font-size: 12px;
+            background-color: black;
+            color: green;
+        }
+    </style>
+    <script>var requirePixelDump = true;</script>
+    <script src=""
+    <script src=""
+    <script>
+    window.addEventListener('load', async event => {
+        findMediaElement();
+
+        run(`video.querySelector("track").src = ""
+        run(`video.textTracks[0].mode = "showing"`);
+        await waitFor(video.querySelector('track'), 'load');
+
+        run(`video.src = "" "w3c/track/webvtt/media/white")`);
+        await waitFor(video, 'canplaythrough');
+
+        endTest();
+    });
+    </script>
+</head>
+<body>
+    <video>
+        <track id="testTrack" kind="captions" default>
+    </video>
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (286742 => 286743)


--- trunk/Source/WebCore/ChangeLog	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/ChangeLog	2021-12-08 22:59:49 UTC (rev 286743)
@@ -1,5 +1,62 @@
 2021-12-08  Jer Noble  <jer.no...@apple.com>
 
+        [VTT] Fix various issues with complicated rendering of VTT cues
+        https://bugs.webkit.org/show_bug.cgi?id=233901
+
+        Reviewed by Eric Carlson.
+
+        Tests: media/track/track-webvtt-no-snap-to-lines-overlap.html
+               media/track/track-webvtt-snap-to-lines-inline-style.html
+               media/track/track-webvtt-snap-to-lines-left-right.html
+
+        When positioning VTT cues, the spec requires UAs to avoid collisions between cues
+        by detecting that two cues overlap each other. However, WebKit's implementation
+        looks for collisions between non-displaying portions of the cues; namely the 
+        ::-webkit-media-text-track-display element, which is used to position the displaying
+        portion of the cue. Instead, the UA should look for collisions between the 
+        ::-webkit-media-text-track-display-backdrop element, which holds the background
+        of the cue, if present.
+
+        Add a convenience function to retrieve the backdrop element, and another to retrieve
+        the cue itself.
+
+        Add cast macros for RenderVTTCue to allow downcast<>ing. Use this macro to retrieve
+        other cues's backdrop elements for collision avoidance.
+
+        VTTCueBox::applyCSSProperties() had a section for moving cues into place that is entirely
+        unneeded if VTTCue::getCSSPosition() returns the pre-calculated m_displayPosition.
+
+        RenderVTTCue::initializeLayoutParameters() is a careful implementation of the specification,
+        accurately layout out cues' initial position so that the text run is exactly at the
+        bottom of the content box. However, if the cue has a border, padding, or extra height,
+        this will result in the cue being pushed outside the content box. To account for this,
+        adjust the inital layout parameter by the difference between the cue text size and the
+        backdrop element size.
+
+        RenderVTTCue::layout() will create a LayoutStateMaintainer, which modifies the behavior of
+        layout machinery during the layout itself. However, certain child renderers get dramatically
+        incorrect results for absoluteBoundingRect() unless the maintainer explicitly sets disableState.
+
+        * html/track/VTTCue.cpp:
+        (WebCore::VTTCueBox::applyCSSProperties):
+        (WebCore::VTTCue::getCSSPosition const):
+        * html/track/VTTCue.h:
+        * rendering/RenderObject.h:
+        (WebCore::RenderObject::isRenderVTTCue const):
+        * rendering/RenderVTTCue.cpp:
+        (WebCore::RenderVTTCue::layout):
+        (WebCore::RenderVTTCue::initializeLayoutParameters):
+        (WebCore::RenderVTTCue::isOutside const):
+        (WebCore::RenderVTTCue::overlappingObject const):
+        (WebCore::RenderVTTCue::overlappingObjectForRect const):
+        (WebCore::RenderVTTCue::moveIfNecessaryToKeepWithinContainer):
+        (WebCore::RenderVTTCue::findNonOverlappingPosition const):
+        (WebCore::RenderVTTCue::repositionGenericCue):
+        (WebCore::RenderVTTCue::backdropBox const):
+        (WebCore::RenderVTTCue::cueBox const):
+
+2021-12-08  Jer Noble  <jer.no...@apple.com>
+
         [MSE] Add a Modules/mediasource/README.md file
         https://bugs.webkit.org/show_bug.cgi?id=234026
         <rdar://problem/86227732>

Modified: trunk/Source/WebCore/html/track/VTTCue.cpp (286742 => 286743)


--- trunk/Source/WebCore/html/track/VTTCue.cpp	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/html/track/VTTCue.cpp	2021-12-08 22:59:49 UTC (rev 286743)
@@ -186,14 +186,15 @@
     // the 'writing-mode' property must be set to writing-mode
     setInlineStyleProperty(CSSPropertyWritingMode, cue->getCSSWritingMode(), false);
 
-    auto position = cue->getCSSPosition();
+    auto& position = cue->getCSSPosition();
 
     // the 'top' property must be set to top,
-    setInlineStyleProperty(CSSPropertyTop, position.second, CSSUnitType::CSS_PERCENTAGE);
+    if (position.second)
+        setInlineStyleProperty(CSSPropertyTop, *position.second, CSSUnitType::CSS_PERCENTAGE);
 
     // the 'left' property must be set to left
-    if (cue->vertical() == horizontalKeyword())
-        setInlineStyleProperty(CSSPropertyLeft, position.first, CSSUnitType::CSS_PERCENTAGE);
+    if (cue->vertical() == horizontalKeyword() && position.first)
+        setInlineStyleProperty(CSSPropertyLeft, *position.first, CSSUnitType::CSS_PERCENTAGE);
     else if (cue->vertical() == verticalGrowingRightKeyword()) {
         // FIXME: Why use calc to do the math instead of doing the subtraction here?
         setInlineStyleProperty(CSSPropertyLeft, makeString("calc(-", videoSize.width(), "px - ", cue->getCSSSize(), "px)"));
@@ -219,15 +220,15 @@
         setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto);
         setInlineStyleProperty(CSSPropertyMinWidth, "min-content");
         setInlineStyleProperty(CSSPropertyMaxWidth, maxSize, CSSUnitType::CSS_PERCENTAGE);
-        if ((alignment == CSSValueMiddle || alignment == CSSValueCenter) && multiplier != 1.0)
-            setInlineStyleProperty(CSSPropertyLeft, static_cast<double>(position.first - (newCueSize - cue->getCSSSize()) / 2), CSSUnitType::CSS_PERCENTAGE);
+        if ((alignment == CSSValueMiddle || alignment == CSSValueCenter) && multiplier != 1.0 && position.first)
+            setInlineStyleProperty(CSSPropertyLeft, static_cast<double>(*position.first - (newCueSize - cue->getCSSSize()) / 2), CSSUnitType::CSS_PERCENTAGE);
     } else {
         setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto);
         setInlineStyleProperty(CSSPropertyHeight, newCueSize, CSSUnitType::CSS_PERCENTAGE);
         setInlineStyleProperty(CSSPropertyMinHeight, "min-content");
         setInlineStyleProperty(CSSPropertyMaxHeight, maxSize, CSSUnitType::CSS_PERCENTAGE);
-        if ((alignment == CSSValueMiddle || alignment == CSSValueCenter) && multiplier != 1.0)
-            setInlineStyleProperty(CSSPropertyTop, static_cast<double>(position.second - (newCueSize - cue->getCSSSize()) / 2), CSSUnitType::CSS_PERCENTAGE);
+        if ((alignment == CSSValueMiddle || alignment == CSSValueCenter) && multiplier != 1.0 && position.second)
+            setInlineStyleProperty(CSSPropertyTop, static_cast<double>(*position.second - (newCueSize - cue->getCSSSize()) / 2), CSSUnitType::CSS_PERCENTAGE);
     }
 
     // The 'text-align' property on the (root) List of WebVTT Node Objects must
@@ -236,21 +237,8 @@
     // alignment:
     setInlineStyleProperty(CSSPropertyTextAlign, cue->getCSSAlignment());
     
-    if (!cue->snapToLines()) {
-        // 10.13.1 Set up x and y:
-        // Note: x and y are set through the CSS left and top above.
-
-        // 10.13.2 Position the boxes in boxes such that the point x% along the
-        // width of the bounding box of the boxes in boxes is x% of the way
-        // across the width of the video's rendering area, and the point y%
-        // along the height of the bounding box of the boxes in boxes is y%
-        // of the way across the height of the video's rendering area, while
-        // maintaining the relative positions of the boxes in boxes to each
-        // other.
-        setInlineStyleProperty(CSSPropertyTransform, makeString("translate(", -position.first, "%, ", -position.second, "%)"));
-
+    if (!cue->snapToLines())
         setInlineStyleProperty(CSSPropertyWhiteSpace, CSSValuePre);
-    }
 
     // Make sure shadow or stroke is not clipped.
     setInlineStyleProperty(CSSPropertyOverflow, CSSValueVisible);
@@ -384,26 +372,21 @@
 
 VTTCue::LineAndPositionSetting VTTCue::line() const
 {
-    if (std::isnan(m_linePosition))
+    if (!m_linePosition)
         return Auto;
 
-    return m_linePosition;
+    return *m_linePosition;
 }
 
 ExceptionOr<void> VTTCue::setLine(const LineAndPositionSetting& position)
 {
-    double linePosition = 0;
+    std::optional<double> linePosition;
 
-    if (std::holds_alternative<AutoKeyword>(position)) {
-        if (std::isnan(m_linePosition))
-            return { };
-        linePosition = std::numeric_limits<double>::quiet_NaN();
-    } else {
+    if (!std::holds_alternative<AutoKeyword>(position))
         linePosition = std::get<double>(position);
 
-        if (m_linePosition == linePosition)
-            return { };
-    }
+    if (m_linePosition == linePosition)
+        return { };
 
     willChange();
     m_linePosition = linePosition;
@@ -453,9 +436,9 @@
 
 VTTCue::LineAndPositionSetting VTTCue::position() const
 {
-    if (textPositionIsAuto())
-        return Auto;
-    return m_textPosition;
+    if (m_textPosition)
+        return *m_textPosition;
+    return Auto;
 }
 
 ExceptionOr<void> VTTCue::setPosition(const LineAndPositionSetting& position)
@@ -465,23 +448,20 @@
     // IndexSizeError exception must be thrown. Otherwise, the WebVTT cue
     // position must be set to the new value; if the new value is the string
     // "auto", then it must be interpreted as the special value auto.
-    double textPosition = 0;
-    if (std::holds_alternative<AutoKeyword>(position)) {
-        if (textPositionIsAuto())
-            return { };
-        textPosition = std::numeric_limits<double>::quiet_NaN();
-    } else {
+    std::optional<double> textPosition;
+
+    // Otherwise, set the text track cue line position to the new value.
+    if (!std::holds_alternative<AutoKeyword>(position)) {
         textPosition = std::get<double>(position);
         if (!(textPosition >= 0 && textPosition <= 100))
             return Exception { IndexSizeError };
-
-        // Otherwise, set the text track cue line position to the new value.
-        if (m_textPosition == textPosition)
-            return { };
     }
 
+    if (m_textPosition == textPosition)
+        return { };
+
     willChange();
-    m_textPosition = textPosition;
+    m_textPosition = WTFMove(textPosition);
     didChange();
 
     return { };
@@ -714,14 +694,14 @@
     return m_region->id();
 }
 
-int VTTCue::calculateComputedLinePosition()
+int VTTCue::calculateComputedLinePosition() const
 {
     // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-computed-line-position
 
     // If the text track cue line position is numeric, then that is the text
     // track cue computed line position.
-    if (!std::isnan(m_linePosition))
-        return m_linePosition;
+    if (m_linePosition)
+        return *m_linePosition;
 
     // If the text track cue snap-to-lines flag of the text track cue is not
     // set, the text track cue computed line position is the value 100;
@@ -756,11 +736,6 @@
     return u_charType(character) == U_PARAGRAPH_SEPARATOR;
 }
 
-bool VTTCue::textPositionIsAuto() const
-{
-    return std::isnan(m_textPosition);
-}
-
 void VTTCue::determineTextDirection()
 {
     static NeverDestroyed<const String> rtTag(MAKE_STATIC_STRING_IMPL("rt"));
@@ -810,8 +785,8 @@
     
     // 1. If the position is numeric, then return the value of the position and
     // abort these steps. (Otherwise, the position is the special value auto.)
-    if (!textPositionIsAuto())
-        return m_textPosition;
+    if (m_textPosition)
+        return *m_textPosition;
     
     switch (m_cueAlignment) {
     case Start:
@@ -921,18 +896,18 @@
     // 10.9 Determine the value of whichever of x-position or y-position is not
     // yet calculated for cue as per the appropriate rules from the following
     // list:
-    if (m_snapToLines && m_displayPosition.second == undefinedPosition && m_writingDirection == Horizontal)
+    if (m_snapToLines && !m_displayPosition.second && m_writingDirection == Horizontal)
         m_displayPosition.second = 0;
 
-    if (!m_snapToLines && m_displayPosition.second == undefinedPosition && m_writingDirection == Horizontal)
-        m_displayPosition.second = m_computedLinePosition;
+    if (!m_snapToLines && !m_displayPosition.second && m_writingDirection == Horizontal)
+        m_displayPosition.second = *m_computedLinePosition;
 
-    if (m_snapToLines && m_displayPosition.first == undefinedPosition
+    if (m_snapToLines && !m_displayPosition.first
         && (m_writingDirection == VerticalGrowingLeft || m_writingDirection == VerticalGrowingRight))
         m_displayPosition.first = 0;
 
     if (!m_snapToLines && (m_writingDirection == VerticalGrowingLeft || m_writingDirection == VerticalGrowingRight))
-        m_displayPosition.first = m_computedLinePosition;
+        m_displayPosition.first = *m_computedLinePosition;
 }
     
 void VTTCue::markFutureAndPastNodes(ContainerNode* root, const MediaTime& previousTimestamp, const MediaTime& movieTime)
@@ -1076,10 +1051,11 @@
     std::pair<double, double> coordinates;
 
     auto textPosition = calculateComputedTextPosition();
+    auto computedLinePosition = m_computedLinePosition ? *m_computedLinePosition : calculateComputedLinePosition();
     
     if (m_writingDirection == Horizontal && m_displayDirection == CSSValueLtr) {
         coordinates.first = textPosition;
-        coordinates.second = m_computedLinePosition;
+        coordinates.second = computedLinePosition;
 
         return coordinates;
     }
@@ -1086,13 +1062,13 @@
 
     if (m_writingDirection == Horizontal && m_displayDirection == CSSValueRtl) {
         coordinates.first = 100 - textPosition;
-        coordinates.second = m_computedLinePosition;
+        coordinates.second = computedLinePosition;
 
         return coordinates;
     }
 
     if (m_writingDirection == VerticalGrowingLeft) {
-        coordinates.first = 100 - m_computedLinePosition;
+        coordinates.first = 100 - *m_computedLinePosition;
         coordinates.second = textPosition;
 
         return coordinates;
@@ -1099,7 +1075,7 @@
     }
 
     if (m_writingDirection == VerticalGrowingRight) {
-        coordinates.first = m_computedLinePosition;
+        coordinates.first = computedLinePosition;
         coordinates.second = textPosition;
 
         return coordinates;
@@ -1319,14 +1295,6 @@
     return m_displaySize;
 }
 
-std::pair<double, double> VTTCue::getCSSPosition() const
-{
-    if (!m_snapToLines)
-        return getPositionCoordinates();
-
-    return m_displayPosition;
-}
-
 bool VTTCue::cueContentsMatch(const TextTrackCue& otherTextTrackCue) const
 {
     auto& other = downcast<VTTCue>(otherTextTrackCue);
@@ -1360,11 +1328,14 @@
 
     object.setString("vertical"_s, vertical());
     object.setBoolean("snapToLines"_s, snapToLines());
-    object.setDouble("line"_s, m_linePosition);
-    if (textPositionIsAuto())
+    if (m_linePosition)
+        object.setString("line"_s, "auto"_s);
+    else
+        object.setDouble("line"_s, *m_linePosition);
+    if (m_textPosition)
+        object.setDouble("position"_s, *m_textPosition);
+    else
         object.setString("position"_s, "auto"_s);
-    else
-        object.setDouble("position"_s, m_textPosition);
     object.setInteger("size"_s, m_cueSize);
     object.setString("align"_s, align());
 }

Modified: trunk/Source/WebCore/html/track/VTTCue.h (286742 => 286743)


--- trunk/Source/WebCore/html/track/VTTCue.h	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/html/track/VTTCue.h	2021-12-08 22:59:49 UTC (rev 286743)
@@ -136,10 +136,11 @@
     void removeDisplayTree() final;
     void markFutureAndPastNodes(ContainerNode*, const MediaTime&, const MediaTime&);
 
-    int calculateComputedLinePosition();
+    int calculateComputedLinePosition() const;
     std::pair<double, double> getPositionCoordinates() const;
 
-    std::pair<double, double> getCSSPosition() const;
+    using DisplayPosition = std::pair<std::optional<double>, std::optional<double>>;
+    const DisplayPosition& getCSSPosition() const { return m_displayPosition; };
 
     CSSValueID getCSSAlignment() const;
     int getCSSSize() const;
@@ -207,8 +208,6 @@
 
     void parseSettings(const String&);
 
-    bool textPositionIsAuto() const;
-
     void determineTextDirection();
     void calculateDisplayParameters();
 
@@ -223,13 +222,11 @@
     };
     CueSetting settingName(VTTScanner&);
 
-    static constexpr double undefinedPosition = -1;
-
     String m_content;
     String m_settings;
-    double m_linePosition { std::numeric_limits<double>::quiet_NaN() };
-    double m_computedLinePosition { std::numeric_limits<double>::quiet_NaN() };
-    double m_textPosition { std::numeric_limits<double>::quiet_NaN() };
+    std::optional<double> m_linePosition;
+    std::optional<double> m_computedLinePosition;
+    std::optional<double> m_textPosition;
     int m_cueSize { 100 };
 
     WritingDirection m_writingDirection { Horizontal };
@@ -245,7 +242,7 @@
 
     CSSValueID m_displayDirection { CSSValueLtr };
     int m_displaySize { 0 };
-    std::pair<float, float> m_displayPosition;
+    DisplayPosition m_displayPosition;
 
     MediaTime m_originalStartTime;
 

Modified: trunk/Source/WebCore/page/CaptionUserPreferences.cpp (286742 => 286743)


--- trunk/Source/WebCore/page/CaptionUserPreferences.cpp	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/page/CaptionUserPreferences.cpp	2021-12-08 22:59:49 UTC (rev 286743)
@@ -97,7 +97,7 @@
 void CaptionUserPreferences::setCaptionDisplayMode(CaptionUserPreferences::CaptionDisplayMode mode)
 {
     m_displayMode = mode;
-    if (m_testingMode && mode != AlwaysOn) {
+    if (testingMode() && mode != AlwaysOn) {
         setUserPrefersCaptions(false);
         setUserPrefersSubtitles(false);
     }
@@ -176,7 +176,7 @@
 Vector<String> CaptionUserPreferences::preferredLanguages() const
 {
     Vector<String> languages = userPreferredLanguages(ShouldMinimizeLanguages::No);
-    if (m_testingMode && !m_userPreferredLanguage.isEmpty())
+    if (testingMode() && !m_userPreferredLanguage.isEmpty())
         languages.insert(0, m_userPreferredLanguage);
 
     return languages;

Modified: trunk/Source/WebCore/page/CaptionUserPreferences.h (286742 => 286743)


--- trunk/Source/WebCore/page/CaptionUserPreferences.h	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/page/CaptionUserPreferences.h	2021-12-08 22:59:49 UTC (rev 286743)
@@ -36,6 +36,7 @@
 
 namespace WebCore {
 
+class CaptionUserPreferencesTestingModeToken;
 class HTMLMediaElement;
 class Page;
 class PageGroup;
@@ -98,8 +99,10 @@
     void setPrimaryAudioTrackLanguageOverride(const String& language) { m_primaryAudioTrackLanguageOverride = language;  }
     String primaryAudioTrackLanguageOverride() const;
 
-    virtual bool testingMode() const { return m_testingMode; }
-    void setTestingMode(bool override) { m_testingMode = override; }
+    virtual bool testingMode() const { return m_testingModeCount; }
+
+    friend class CaptionUserPreferencesTestingModeToken;
+    UniqueRef<CaptionUserPreferencesTestingModeToken> createTestingModeToken() { return makeUniqueRef<CaptionUserPreferencesTestingModeToken>(*this); }
     
     PageGroup& pageGroup() const { return m_pageGroup; }
 
@@ -111,6 +114,14 @@
     void endBlockingNotifications();
 
 private:
+    void incrementTestingModeCount() { ++m_testingModeCount; }
+    void decrementTestingModeCount()
+    {
+        ASSERT(m_testingModeCount);
+        if (m_testingModeCount)
+            --m_testingModeCount;
+    }
+
     void timerFired();
     void notify();
     Page* currentPage() const;
@@ -123,9 +134,26 @@
     String m_captionsStyleSheetOverride;
     String m_primaryAudioTrackLanguageOverride;
     unsigned m_blockNotificationsCounter { 0 };
-    bool m_testingMode { false };
     bool m_havePreferences { false };
+    unsigned m_testingModeCount { 0 };
 };
+
+class CaptionUserPreferencesTestingModeToken {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    CaptionUserPreferencesTestingModeToken(CaptionUserPreferences& parent)
+        : m_parent(parent)
+    {
+        parent.incrementTestingModeCount();
+    }
+    ~CaptionUserPreferencesTestingModeToken()
+    {
+        if (m_parent)
+            m_parent->decrementTestingModeCount();
+    }
+private:
+    WeakPtr<CaptionUserPreferences> m_parent;
+};
     
 }
 

Modified: trunk/Source/WebCore/rendering/RenderObject.h (286742 => 286743)


--- trunk/Source/WebCore/rendering/RenderObject.h	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/rendering/RenderObject.h	2021-12-08 22:59:49 UTC (rev 286743)
@@ -269,6 +269,7 @@
     virtual bool isRenderMultiColumnSpannerPlaceholder() const { return false; }
 
     virtual bool isRenderScrollbarPart() const { return false; }
+    virtual bool isRenderVTTCue() const { return false; }
 
     bool isDocumentElementRenderer() const { return document().documentElement() == &m_node; }
     bool isBody() const { return node() && node()->hasTagName(HTMLNames::bodyTag); }

Modified: trunk/Source/WebCore/rendering/RenderVTTCue.cpp (286742 => 286743)


--- trunk/Source/WebCore/rendering/RenderVTTCue.cpp	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/rendering/RenderVTTCue.cpp	2021-12-08 22:59:49 UTC (rev 286743)
@@ -60,7 +60,7 @@
     if (!m_cue->regionId().isEmpty())
         return;
 
-    LayoutStateMaintainer statePusher(*this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
+    LayoutStateMaintainer statePusher(*this, locationOffset(), true);
 
     if (m_cue->cueType()== TextTrackCue::WebVTT) {
         if (m_cue->snapToLines())
@@ -79,12 +79,7 @@
 
     RenderBlock* parentBlock = containingBlock();
 
-    // firstChild() returns the wrapping (backdrop) <div>. The cue object is
-    // the <div>'s first child.
-    RenderObject& firstChild = *this->firstChild();
-    RenderElement& backdropElement = downcast<RenderElement>(firstChild);
-    
-    firstLineBox = downcast<RenderInline>(*backdropElement.firstChild()).firstLineBox();
+    firstLineBox = cueBox().firstLineBox();
     if (!firstLineBox)
         firstLineBox = this->firstRootBox();
 
@@ -92,6 +87,23 @@
     //    Vertical: Let step be the width of the first line box in boxes.
     step = m_cue->getWritingDirection() == VTTCue::Horizontal ? firstLineBox->height() : firstLineBox->width();
 
+    // Note: the previous rules in initializeLayoutParameters() only account for
+    // the height of the line boxes contained within the cue, and not the cue's height
+    // nor its padding, nor its borders. Ignoring these will lead to errors
+    // in the initial placement of cues, as the resulting placement will result in
+    // the cue always being partially outside its containing block, rather than at
+    // its initial position. Correct the initial position by subtracting from
+    // position the difference between the the logicalHeight of the cue and its
+    // first line box.
+    auto& backdropBox = this->backdropBox();
+    auto lineBoxHeights = firstLineBox->logicalHeight();
+    for (auto nextLineBox = firstLineBox->nextLineBox(); nextLineBox; nextLineBox = nextLineBox->nextLineBox())
+        lineBoxHeights += nextLineBox->logicalHeight();
+
+    auto logicalHeightDelta = backdropBox.logicalHeight() - lineBoxHeights;
+    if (logicalHeightDelta > 0)
+        step += logicalHeightDelta;
+
     // 2. If step is zero, then jump to the step labeled done positioning below.
     if (!step)
         return false;
@@ -146,7 +158,7 @@
 
 bool RenderVTTCue::isOutside() const
 {
-    return !rectIsWithinContainer(absoluteContentBox());
+    return !rectIsWithinContainer(backdropBox().absoluteBoundingBoxRect());
 }
 
 bool RenderVTTCue::rectIsWithinContainer(const IntRect& rect) const
@@ -160,18 +172,20 @@
     return overlappingObject();
 }
 
-RenderObject* RenderVTTCue::overlappingObject() const
+RenderVTTCue* RenderVTTCue::overlappingObject() const
 {
-    return overlappingObjectForRect(absoluteBoundingBoxRect());
+    return overlappingObjectForRect(backdropBox().absoluteBoundingBoxRect());
 }
 
-RenderObject* RenderVTTCue::overlappingObjectForRect(const IntRect& rect) const
+RenderVTTCue* RenderVTTCue::overlappingObjectForRect(const IntRect& rect) const
 {
-    for (RenderObject* box = previousSibling(); box; box = box->previousSibling()) {
-        IntRect boxRect = box->absoluteBoundingBoxRect();
+    for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling->previousSibling()) {
+        auto* previousCue = downcast<RenderVTTCue>(sibling);
+        if (!previousCue)
+            continue;
 
-        if (rect.intersects(boxRect))
-            return box;
+        if (rect.intersects(previousCue->backdropBox().absoluteBoundingBoxRect()))
+            return previousCue;
     }
 
     return 0;
@@ -243,7 +257,7 @@
 void RenderVTTCue::moveIfNecessaryToKeepWithinContainer()
 {
     IntRect containerRect = containingBlock()->absoluteBoundingBoxRect();
-    IntRect cueRect = absoluteBoundingBoxRect();
+    IntRect cueRect = backdropBox().absoluteBoundingBoxRect();
 
     int topOverflow = cueRect.y() - containerRect.y();
     int bottomOverflow = containerRect.maxY() - cueRect.maxY();
@@ -274,15 +288,15 @@
 {
     newX = x();
     newY = y();
-    IntRect srcRect = absoluteBoundingBoxRect();
+    IntRect srcRect = backdropBox().absoluteBoundingBoxRect();
     IntRect destRect = srcRect;
 
     // Move the box up, looking for a non-overlapping position:
-    while (RenderObject* box = overlappingObjectForRect(destRect)) {
+    while (RenderVTTCue* cue = overlappingObjectForRect(destRect)) {
         if (m_cue->getWritingDirection() == VTTCue::Horizontal)
-            destRect.setY(box->absoluteBoundingBoxRect().y() - destRect.height());
+            destRect.setY(cue->backdropBox().absoluteBoundingBoxRect().y() - destRect.height());
         else
-            destRect.setX(box->absoluteBoundingBoxRect().x() - destRect.width());
+            destRect.setX(cue->backdropBox().absoluteBoundingBoxRect().x() - destRect.width());
     }
 
     if (rectIsWithinContainer(destRect)) {
@@ -294,11 +308,11 @@
     destRect = srcRect;
 
     // Move the box down, looking for a non-overlapping position:
-    while (RenderObject* box = overlappingObjectForRect(destRect)) {
+    while (RenderVTTCue* cue = overlappingObjectForRect(destRect)) {
         if (m_cue->getWritingDirection() == VTTCue::Horizontal)
-            destRect.setY(box->absoluteBoundingBoxRect().maxY());
+            destRect.setY(cue->backdropBox().absoluteBoundingBoxRect().maxY());
         else
-            destRect.setX(box->absoluteBoundingBoxRect().maxX());
+            destRect.setX(cue->backdropBox().absoluteBoundingBoxRect().maxX());
     }
 
     if (rectIsWithinContainer(destRect)) {
@@ -345,12 +359,7 @@
 {
     ASSERT(firstChild());
 
-    // firstChild() returns the wrapping (backdrop) <div>. The cue object is
-    // the <div>'s first child.
-    RenderObject& firstChild = *this->firstChild();
-    RenderElement& backdropElement = downcast<RenderElement>(firstChild);
-    
-    LegacyInlineFlowBox* firstLineBox = downcast<RenderInline>(*backdropElement.firstChild()).firstLineBox();
+    LegacyInlineFlowBox* firstLineBox = cueBox().firstLineBox();
     if (downcast<TextTrackCueGeneric>(*m_cue).useDefaultPosition() && firstLineBox) {
         LayoutUnit parentWidth = containingBlock()->logicalWidth();
         LayoutUnit width { firstLineBox->width() };
@@ -384,6 +393,21 @@
     setY(y);
 }
 
+RenderBlockFlow& RenderVTTCue::backdropBox() const
+{
+    ASSERT(firstChild());
+
+    // firstChild() returns the wrapping (backdrop) <div>. The cue object is
+    // the <div>'s first child.
+    RenderObject& firstChild = *this->firstChild();
+    return downcast<RenderBlockFlow>(firstChild);
+}
+
+RenderInline& RenderVTTCue::cueBox() const
+{
+    return downcast<RenderInline>(*backdropBox().firstChild());
+}
+
 } // namespace WebCore
 
 #endif

Modified: trunk/Source/WebCore/rendering/RenderVTTCue.h (286742 => 286743)


--- trunk/Source/WebCore/rendering/RenderVTTCue.h	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/rendering/RenderVTTCue.h	2021-12-08 22:59:49 UTC (rev 286743)
@@ -42,13 +42,15 @@
     RenderVTTCue(VTTCueBox&, RenderStyle&&);
 
 private:
+    bool isRenderVTTCue() const final { return true; }
+
     void layout() override;
 
     bool isOutside() const;
     bool rectIsWithinContainer(const IntRect&) const;
     bool isOverlapping() const;
-    RenderObject* overlappingObject() const;
-    RenderObject* overlappingObjectForRect(const IntRect&) const;
+    RenderVTTCue* overlappingObject() const;
+    RenderVTTCue* overlappingObjectForRect(const IntRect&) const;
     bool shouldSwitchDirection(LegacyInlineFlowBox*, LayoutUnit) const;
 
     void moveBoxesByStep(LayoutUnit);
@@ -62,6 +64,9 @@
     void repositionCueSnapToLinesNotSet();
     void repositionGenericCue();
 
+    RenderBlockFlow& backdropBox() const;
+    RenderInline& cueBox() const;
+
     VTTCue* m_cue;
     FloatPoint m_fallbackPosition;
 };
@@ -68,4 +73,6 @@
 
 } // namespace WebCore
 
+SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderVTTCue, isRenderVTTCue())
+
 #endif // ENABLE(VIDEO)

Modified: trunk/Source/WebCore/testing/Internals.cpp (286742 => 286743)


--- trunk/Source/WebCore/testing/Internals.cpp	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/testing/Internals.cpp	2021-12-08 22:59:49 UTC (rev 286743)
@@ -545,10 +545,8 @@
     page.mainFrame().loader().clearTestingOverrides();
     page.applicationCacheStorage().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
 #if ENABLE(VIDEO)
-    page.group().ensureCaptionPreferences().setTestingMode(true);
     page.group().ensureCaptionPreferences().setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
     page.group().ensureCaptionPreferences().setCaptionsStyleSheetOverride(emptyString());
-    page.group().ensureCaptionPreferences().setTestingMode(false);
     PlatformMediaSessionManager::sharedManager().resetHaveEverRegisteredAsNowPlayingApplicationForTesting();
     PlatformMediaSessionManager::sharedManager().resetRestrictions();
     PlatformMediaSessionManager::sharedManager().setWillIgnoreSystemInterruptions(true);
@@ -624,14 +622,14 @@
     , m_orientationNotifier(0)
 #endif
 {
-#if ENABLE(VIDEO)
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
     if (document.page())
-        document.page()->group().ensureCaptionPreferences().setTestingMode(true);
+        document.page()->setMockMediaPlaybackTargetPickerEnabled(true);
 #endif
 
-#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#if ENABLE(VIDEO)
     if (document.page())
-        document.page()->setMockMediaPlaybackTargetPickerEnabled(true);
+        m_testingModeToken = document.page()->group().ensureCaptionPreferences().createTestingModeToken().moveToUniquePtr();
 #endif
 
     if (contextDocument() && contextDocument()->frame()) {

Modified: trunk/Source/WebCore/testing/Internals.h (286742 => 286743)


--- trunk/Source/WebCore/testing/Internals.h	2021-12-08 22:57:36 UTC (rev 286742)
+++ trunk/Source/WebCore/testing/Internals.h	2021-12-08 22:59:49 UTC (rev 286743)
@@ -56,6 +56,7 @@
 class BaseAudioContext;
 class Blob;
 class CacheStorageConnection;
+class CaptionUserPreferencesTestingModeToken;
 class DOMPointReadOnly;
 class DOMRect;
 class DOMRectList;
@@ -1262,6 +1263,9 @@
 #if ENABLE(MEDIA_SESSION_COORDINATOR)
     RefPtr<MockMediaSessionCoordinator> m_mockMediaSessionCoordinator;
 #endif
+#if ENABLE(VIDEO)
+    std::unique_ptr<CaptionUserPreferencesTestingModeToken> m_testingModeToken;
+#endif
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to