Title: [150452] trunk
Revision
150452
Author
[email protected]
Date
2013-05-21 10:14:53 -0700 (Tue, 21 May 2013)

Log Message

Implement overlap avoidance for cues with snap-to-lines flag not set
https://bugs.webkit.org/show_bug.cgi?id=84296

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/track/track-cue-overlap-snap-to-lines-not-set.html

Support overlap avoidance for the non-snap-to-lines part of the WebVTT spec.

* rendering/RenderTextTrackCue.cpp:
(WebCore::RenderTextTrackCue::isOutside): Split implementation into rectIsWithinContainer().
(WebCore::RenderTextTrackCue::rectIsWithinContainer): Ditto.
(WebCore::RenderTextTrackCue::isOverlapping): Split into overlappingObject() and overlappingObjectForRect().
(WebCore::RenderTextTrackCue::overlappingObject): Ditto.
(WebCore::RenderTextTrackCue::overlappingObjectForRect): Ditto.
(WebCore::RenderTextTrackCue::moveIfNecessaryToKeepWithinContainer): Added.
(WebCore::RenderTextTrackCue::findNonOverlappingPosition): When an overlapping object is found, move the
    cue to just above or below that object and try again.
(WebCore::RenderTextTrackCue::repositionCueSnapToLinesSet): Move implementation into moveIfNecessaryToKeepWithinContainer().
(WebCore::RenderTextTrackCue::repositionCueSnapToLinesNotSet): Add implementanton based on above.
* rendering/RenderTextTrackCue.h:

LayoutTests:

* media/track/track-cue-overlap-snap-to-lines-not-set-expected.txt: Added.
* media/track/track-cue-overlap-snap-to-lines-not-set.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (150451 => 150452)


--- trunk/LayoutTests/ChangeLog	2013-05-21 16:57:55 UTC (rev 150451)
+++ trunk/LayoutTests/ChangeLog	2013-05-21 17:14:53 UTC (rev 150452)
@@ -1,3 +1,13 @@
+2013-05-20  Jer Noble  <[email protected]>
+
+        Implement overlap avoidance for cues with snap-to-lines flag not set
+        https://bugs.webkit.org/show_bug.cgi?id=84296
+
+        Reviewed by Eric Carlson.
+
+        * media/track/track-cue-overlap-snap-to-lines-not-set-expected.txt: Added.
+        * media/track/track-cue-overlap-snap-to-lines-not-set.html: Added.
+
 2013-05-21  Krzysztof Czech  <[email protected]>
 
         [GTK][WK2] accessibility/label-for-control-hittest.html is failing

Added: trunk/LayoutTests/media/track/track-cue-overlap-snap-to-lines-not-set-expected.txt (0 => 150452)


--- trunk/LayoutTests/media/track/track-cue-overlap-snap-to-lines-not-set-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/track/track-cue-overlap-snap-to-lines-not-set-expected.txt	2013-05-21 17:14:53 UTC (rev 150452)
@@ -0,0 +1,7 @@
+Test that TextTrack's cues are rendered correctly when the snap to lines flag is not set.
+EVENT(canplaythrough)
+EVENT(seeked)
+Active cues: 7
+No cue elements overlap. OK
+END OF TEST
+

Added: trunk/LayoutTests/media/track/track-cue-overlap-snap-to-lines-not-set.html (0 => 150452)


--- trunk/LayoutTests/media/track/track-cue-overlap-snap-to-lines-not-set.html	                        (rev 0)
+++ trunk/LayoutTests/media/track/track-cue-overlap-snap-to-lines-not-set.html	2013-05-21 17:14:53 UTC (rev 150452)
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <script src=""
+        <script src=""
+        <script src=""
+
+        <script>
+
+        var cueDisplayElement;
+
+        ClientRect.prototype.intersects = function(that)
+        {
+            // Separating axis theorem:
+            return Math.abs(this.top - that.top) < Math.abs(this.height + that.height) / 2
+                && Math.abs(this.left - that.left) < Math.abs(this.width + that.width) / 2;
+        }
+
+        function findOverlappingElement(element)
+        {
+            var elementRect = element.getBoundingClientRect();
+            var siblings = element.parentElement.children;
+            for (var i = 0; i < siblings.length; ++i) {
+                var sibling = siblings[i];
+                if (sibling === element)
+                    continue;
+
+                var siblingRect = sibling.getBoundingClientRect();
+                if (elementRect.intersects(siblingRect))
+                    return sibling;
+            }
+            return null;
+        }
+
+        function seeked()
+        {
+            testTrack = document.querySelector('track');
+            consoleWrite("Active cues: " + testTrack.track.activeCues.length);
+
+            for (var i = 0; i < testTrack.track.activeCues.length; ++i) {
+                var cueDisplayElement = textTrackDisplayElement(video, 'display', i);
+                var overlappingElement = findOverlappingElement(cueDisplayElement);
+                if (overlappingElement) {
+                    failTest("Cue element number " + i + " overlaps with element " + overlappingElement + ".");
+                    return;
+                }
+            }
+
+            logResult(true, "No cue elements overlap.");
+            endTest();
+        };
+
+        function loaded()
+        {
+            consoleWrite("Test that TextTrack's cues are rendered correctly when the snap to lines flag is not set.");
+
+            findMediaElement();
+            video.src = "" '../content/test');
+
+            waitForEvent('canplaythrough', function() {
+                waitForEvent('seeked', seeked, false, true);
+                video.currentTime = 4.10;
+            });
+        }
+
+        </script>
+    </head>
+    <body _onload_="loaded()">
+        <video controls>
+            <track src="" kind="captions" default>
+        </video>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (150451 => 150452)


--- trunk/Source/WebCore/ChangeLog	2013-05-21 16:57:55 UTC (rev 150451)
+++ trunk/Source/WebCore/ChangeLog	2013-05-21 17:14:53 UTC (rev 150452)
@@ -1,3 +1,27 @@
+2013-05-20  Jer Noble  <[email protected]>
+
+        Implement overlap avoidance for cues with snap-to-lines flag not set
+        https://bugs.webkit.org/show_bug.cgi?id=84296
+
+        Reviewed by Eric Carlson.
+
+        Test: media/track/track-cue-overlap-snap-to-lines-not-set.html
+
+        Support overlap avoidance for the non-snap-to-lines part of the WebVTT spec.
+
+        * rendering/RenderTextTrackCue.cpp:
+        (WebCore::RenderTextTrackCue::isOutside): Split implementation into rectIsWithinContainer().
+        (WebCore::RenderTextTrackCue::rectIsWithinContainer): Ditto.
+        (WebCore::RenderTextTrackCue::isOverlapping): Split into overlappingObject() and overlappingObjectForRect().
+        (WebCore::RenderTextTrackCue::overlappingObject): Ditto.
+        (WebCore::RenderTextTrackCue::overlappingObjectForRect): Ditto.
+        (WebCore::RenderTextTrackCue::moveIfNecessaryToKeepWithinContainer): Added.
+        (WebCore::RenderTextTrackCue::findNonOverlappingPosition): When an overlapping object is found, move the
+            cue to just above or below that object and try again.
+        (WebCore::RenderTextTrackCue::repositionCueSnapToLinesSet): Move implementation into moveIfNecessaryToKeepWithinContainer().
+        (WebCore::RenderTextTrackCue::repositionCueSnapToLinesNotSet): Add implementanton based on above.
+        * rendering/RenderTextTrackCue.h:
+
 2013-05-21  Alberto Garcia  <[email protected]>
 
         Remove GraphicsLayerClient::contentsVisible()

Modified: trunk/Source/WebCore/rendering/RenderTextTrackCue.cpp (150451 => 150452)


--- trunk/Source/WebCore/rendering/RenderTextTrackCue.cpp	2013-05-21 16:57:55 UTC (rev 150451)
+++ trunk/Source/WebCore/rendering/RenderTextTrackCue.cpp	2013-05-21 17:14:53 UTC (rev 150452)
@@ -124,19 +124,35 @@
 
 bool RenderTextTrackCue::isOutside() const
 {
-    return !containingBlock()->absoluteBoundingBoxRect().contains(absoluteContentBox());
+    return !rectIsWithinContainer(absoluteContentBox());
 }
 
+bool RenderTextTrackCue::rectIsWithinContainer(const IntRect& rect) const
+{
+    return containingBlock()->absoluteBoundingBoxRect().contains(rect);
+}
+
+
 bool RenderTextTrackCue::isOverlapping() const
 {
+    return overlappingObject();
+}
+
+RenderObject* RenderTextTrackCue::overlappingObject() const
+{
+    return overlappingObjectForRect(absoluteBoundingBoxRect());
+}
+
+RenderObject* RenderTextTrackCue::overlappingObjectForRect(const IntRect& rect) const
+{
     for (RenderObject* box = previousSibling(); box; box = box->previousSibling()) {
         IntRect boxRect = box->absoluteBoundingBoxRect();
 
-        if (absoluteBoundingBoxRect().intersects(boxRect))
-            return true;
+        if (rect.intersects(boxRect))
+            return box;
     }
 
-    return false;
+    return 0;
 }
 
 bool RenderTextTrackCue::shouldSwitchDirection(InlineFlowBox* firstLineBox, LayoutUnit step) const
@@ -202,6 +218,76 @@
     return true;
 }
 
+void RenderTextTrackCue::moveIfNecessaryToKeepWithinContainer()
+{
+    IntRect containerRect = containingBlock()->absoluteBoundingBoxRect();
+    IntRect cueRect = absoluteBoundingBoxRect();
+
+    int topOverflow = cueRect.y() - containerRect.y();
+    int bottomOverflow = containerRect.maxY() - cueRect.maxY();
+
+    int verticalAdjustment = 0;
+    if (topOverflow < 0)
+        verticalAdjustment = -topOverflow;
+    else if (bottomOverflow < 0)
+        verticalAdjustment = bottomOverflow;
+
+    if (verticalAdjustment)
+        setY(y() + verticalAdjustment);
+
+    int leftOverflow = cueRect.x() - containerRect.x();
+    int rightOverflow = containerRect.maxX() - cueRect.maxX();
+
+    int horizontalAdjustment = 0;
+    if (leftOverflow < 0)
+        horizontalAdjustment = -leftOverflow;
+    else if (rightOverflow < 0)
+        horizontalAdjustment = rightOverflow;
+
+    if (horizontalAdjustment)
+        setX(x() + horizontalAdjustment);
+}
+
+bool RenderTextTrackCue::findNonOverlappingPosition(int& newX, int& newY) const
+{
+    newX = x();
+    newY = y();
+    IntRect srcRect = absoluteBoundingBoxRect();
+    IntRect destRect = srcRect;
+
+    // Move the box up, looking for a non-overlapping position:
+    while (RenderObject* box = overlappingObjectForRect(destRect)) {
+        if (m_cue->getWritingDirection() == TextTrackCue::Horizontal)
+            destRect.setY(box->absoluteBoundingBoxRect().y() - destRect.height());
+        else
+            destRect.setX(box->absoluteBoundingBoxRect().x() - destRect.width());
+    }
+
+    if (rectIsWithinContainer(destRect)) {
+        newX += destRect.x() - srcRect.x();
+        newY += destRect.y() - srcRect.y();
+        return true;
+    }
+
+    destRect = srcRect;
+
+    // Move the box down, looking for a non-overlapping position:
+    while (RenderObject* box = overlappingObjectForRect(destRect)) {
+        if (m_cue->getWritingDirection() == TextTrackCue::Horizontal)
+            destRect.setY(box->absoluteBoundingBoxRect().maxY());
+        else
+            destRect.setX(box->absoluteBoundingBoxRect().maxX());
+    }
+
+    if (rectIsWithinContainer(destRect)) {
+        newX += destRect.x() - srcRect.x();
+        newY += destRect.y() - srcRect.y();
+        return true;
+    }
+
+    return false;
+}
+
 void RenderTextTrackCue::repositionCueSnapToLinesSet()
 {
     InlineFlowBox* firstLineBox;
@@ -229,22 +315,8 @@
 
     // Acommodate extra top and bottom padding, border or margin.
     // Note: this is supported only for internal UA styling, not through the cue selector.
-    if (hasInlineDirectionBordersPaddingOrMargin()) {
-        IntRect containerRect = containingBlock()->absoluteBoundingBoxRect();
-        IntRect cueRect = absoluteBoundingBoxRect();
-
-        int topOverflow = cueRect.y() - containerRect.y();
-        int bottomOverflow = containerRect.y() + containerRect.height() - cueRect.y() - cueRect.height();
-
-        int adjustment = 0;
-        if (topOverflow < 0)
-            adjustment = -topOverflow;
-        else if (bottomOverflow < 0)
-            adjustment = bottomOverflow;
-
-        if (adjustment)
-            setY(y() + adjustment);
-    }
+    if (hasInlineDirectionBordersPaddingOrMargin())
+        moveIfNecessaryToKeepWithinContainer();
 }
 
 void RenderTextTrackCue::repositionGenericCue()
@@ -267,7 +339,26 @@
 
 void RenderTextTrackCue::repositionCueSnapToLinesNotSet()
 {
-    // FIXME: Implement overlapping detection when snap-to-lines is not set. http://wkb.ug/84296
+    // 3. If none of the boxes in boxes would overlap any of the boxes in output, and all the boxes in
+    // output are within the video's rendering area, then jump to the step labeled done positioning below.
+    if (!isOutside() && !isOverlapping())
+        return;
+
+    // 4. If there is a position to which the boxes in boxes can be moved while maintaining the relative
+    // positions of the boxes in boxes to each other such that none of the boxes in boxes would overlap
+    // any of the boxes in output, and all the boxes in output would be within the video's rendering area,
+    // then move the boxes in boxes to the closest such position to their current position, and then jump
+    // to the step labeled done positioning below. If there are multiple such positions that are equidistant
+    // from their current position, use the highest one amongst them; if there are several at that height,
+    // then use the leftmost one amongst them.
+    moveIfNecessaryToKeepWithinContainer();
+    int x = 0;
+    int y = 0;
+    if (!findNonOverlappingPosition(x, y))
+        return;
+
+    setX(x);
+    setY(y);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/RenderTextTrackCue.h (150451 => 150452)


--- trunk/Source/WebCore/rendering/RenderTextTrackCue.h	2013-05-21 16:57:55 UTC (rev 150451)
+++ trunk/Source/WebCore/rendering/RenderTextTrackCue.h	2013-05-21 17:14:53 UTC (rev 150452)
@@ -35,6 +35,7 @@
 
 namespace WebCore {
 
+class RenderBox;
 class TextTrackCueBox;
 
 class RenderTextTrackCue : public RenderBlock {
@@ -45,11 +46,16 @@
     virtual void layout() OVERRIDE;
 
     bool isOutside() const;
+    bool rectIsWithinContainer(const IntRect&) const;
     bool isOverlapping() const;
+    RenderObject* overlappingObject() const;
+    RenderObject* overlappingObjectForRect(const IntRect&) const;
     bool shouldSwitchDirection(InlineFlowBox*, LayoutUnit) const;
 
     void moveBoxesByStep(LayoutUnit);
     bool switchDirection(bool&, LayoutUnit&);
+    void moveIfNecessaryToKeepWithinContainer();
+    bool findNonOverlappingPosition(int& x, int& y) const;
 
     bool initializeLayoutParameters(InlineFlowBox*&, LayoutUnit&, LayoutUnit&);
     void placeBoxInDefaultPosition(LayoutUnit, bool&);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to