Implement overlap-avoidance for in-band text track cues.
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 May 2013 17:16:34 +0000 (17:16 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 May 2013 17:16:34 +0000 (17:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=116540

Reviewed by Eric Carlson.

In-band (or Generic) cues need special casing for certain features
present in in-band tracks, like paint-on and roll-up modes. To avoid
the problem of overlap avoidance forcing a caption meant to appear
below a cue to appear above it when a larger font size is selected,
impose an additional sort ordering for "generic cues". Instead of
cues being ordered by the order they appear in the track, "generic
cues" further sorted by their position within the video area, such
that cues at the bottom of the video area appear first, and later
cues are pushed up to avoid them, preserving the desired apparent
ordering.

* html/HTMLMediaElement.cpp:
(WebCore::compareCueInterval): Added; wrapper around
    TextTrackCue::isOrderedBefore.
(WebCore::HTMLMediaElement::updateActiveTextTrackCues):
    After creating the list of current cues, sort them.
* html/track/TextTrackCue.cpp:
(WebCore::TextTrackCue::isOrderedBefore): Added; implementation moved
    from TextTrackCueList::add().
* html/track/TextTrackCue.h:
* html/track/TextTrackCueGeneric.cpp:
(WebCore::TextTrackCueGeneric::isOrderedBefore): Added override;
    impose additional oredring on generic cues.
* html/track/TextTrackCueGeneric.h:
* html/track/TextTrackCueList.cpp:
(WebCore::TextTrackCueList::add): Moved ordering test into
    isOrderedBefore().
* rendering/RenderTextTrackCue.cpp:
(WebCore::RenderTextTrackCue::repositionGenericCue):
    Call repositionCueSnapToLinesNotSet() after positioning the cue.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@150453 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/track/TextTrackCue.cpp
Source/WebCore/html/track/TextTrackCue.h
Source/WebCore/html/track/TextTrackCueGeneric.cpp
Source/WebCore/html/track/TextTrackCueGeneric.h
Source/WebCore/html/track/TextTrackCueList.cpp
Source/WebCore/rendering/RenderTextTrackCue.cpp

index 66b5738..01d2f6a 100644 (file)
@@ -1,3 +1,41 @@
+2013-05-21  Jer Noble  <jer.noble@apple.com>
+
+        Implement overlap-avoidance for in-band text track cues.
+        https://bugs.webkit.org/show_bug.cgi?id=116540
+
+        Reviewed by Eric Carlson.
+
+        In-band (or Generic) cues need special casing for certain features
+        present in in-band tracks, like paint-on and roll-up modes. To avoid
+        the problem of overlap avoidance forcing a caption meant to appear
+        below a cue to appear above it when a larger font size is selected,
+        impose an additional sort ordering for "generic cues". Instead of
+        cues being ordered by the order they appear in the track, "generic
+        cues" further sorted by their position within the video area, such
+        that cues at the bottom of the video area appear first, and later
+        cues are pushed up to avoid them, preserving the desired apparent
+        ordering.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::compareCueInterval): Added; wrapper around
+            TextTrackCue::isOrderedBefore.
+        (WebCore::HTMLMediaElement::updateActiveTextTrackCues):
+            After creating the list of current cues, sort them.
+        * html/track/TextTrackCue.cpp:
+        (WebCore::TextTrackCue::isOrderedBefore): Added; implementation moved
+            from TextTrackCueList::add().
+        * html/track/TextTrackCue.h:
+        * html/track/TextTrackCueGeneric.cpp:
+        (WebCore::TextTrackCueGeneric::isOrderedBefore): Added override;
+            impose additional oredring on generic cues.
+        * html/track/TextTrackCueGeneric.h:
+        * html/track/TextTrackCueList.cpp:
+        (WebCore::TextTrackCueList::add): Moved ordering test into
+            isOrderedBefore().
+        * rendering/RenderTextTrackCue.cpp:
+        (WebCore::RenderTextTrackCue::repositionGenericCue):
+            Call repositionCueSnapToLinesNotSet() after positioning the cue.
+
 2013-05-20  Jer Noble  <jer.noble@apple.com>
 
         Implement overlap avoidance for cues with snap-to-lines flag not set
index 15f26ba..a1d4b0a 100644 (file)
@@ -1116,6 +1116,11 @@ static bool eventTimeCueCompare(const std::pair<double, TextTrackCue*>& a,
     return a.second->cueIndex() - b.second->cueIndex() < 0;
 }
 
+static bool compareCueInterval(const CueInterval& one, const CueInterval& two)
+{
+    return one.data()->isOrderedBefore(two.data());
+};
+
 
 void HTMLMediaElement::updateActiveTextTrackCues(double movieTime)
 {
@@ -1138,8 +1143,10 @@ void HTMLMediaElement::updateActiveTextTrackCues(double movieTime)
 
     // The user agent must synchronously unset [the text track cue active] flag
     // whenever ... the media element's readyState is changed back to HAVE_NOTHING.
-    if (m_readyState != HAVE_NOTHING && m_player)
+    if (m_readyState != HAVE_NOTHING && m_player) {
         currentCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime));
+        std::sort(currentCues.begin(), currentCues.end(), &compareCueInterval);
+    }
 
     CueList previousCues;
     CueList missedCues;
index dae6b83..5bd5641 100644 (file)
@@ -1195,6 +1195,12 @@ bool TextTrackCue::isEqual(const TextTrackCue& cue, CueMatchRules match) const
     
     return true;
 }
+
+bool TextTrackCue::isOrderedBefore(const TextTrackCue* other) const
+{
+    return startTime() < other->startTime() || (startTime() == other->startTime() && endTime() > other->endTime());
+}
+
 void TextTrackCue::setFontSize(int fontSize, const IntSize&, bool important)
 {
     if (!hasDisplayTree() || !fontSize)
index a7f09bd..724e78b 100644 (file)
@@ -151,6 +151,7 @@ public:
     void markFutureAndPastNodes(ContainerNode*, double, double);
 
     int calculateComputedLinePosition();
+    std::pair<double, double> getPositionCoordinates() const;
 
     virtual const AtomicString& interfaceName() const;
     virtual ScriptExecutionContext* scriptExecutionContext() const;
@@ -184,6 +185,8 @@ public:
     };
     virtual bool isEqual(const TextTrackCue&, CueMatchRules) const;
 
+    virtual bool isOrderedBefore(const TextTrackCue*) const;
+
     enum CueType {
         Generic,
         WebVTT
@@ -214,7 +217,6 @@ private:
     void createWebVTTNodeTree();
     void copyWebVTTNodeToDOMTree(ContainerNode* WebVTTNode, ContainerNode* root);
 
-    std::pair<double, double> getPositionCoordinates() const;
     void parseSettings(const String&);
 
     void determineTextDirection();
index e97ae25..d871271 100644 (file)
@@ -172,6 +172,21 @@ bool TextTrackCueGeneric::isEqual(const TextTrackCue& cue, TextTrackCue::CueMatc
 
     return TextTrackCue::isEqual(cue, match);
 }
+
+bool TextTrackCueGeneric::isOrderedBefore(const TextTrackCue* that) const
+{
+    if (TextTrackCue::isOrderedBefore(that))
+        return true;
+
+    if (that->cueType() == WebVTT && startTime() == that->startTime() && endTime() == that->endTime()) {
+        // Further order generic cues by their calculated line value.
+        std::pair<double, double> thisPosition = getPositionCoordinates();
+        std::pair<double, double> thatPosition = that->getPositionCoordinates();
+        return thisPosition.second > thatPosition.second || (thisPosition.second == thatPosition.second && thisPosition.first < thatPosition.first);
+    }
+
+    return false;
+}
     
 } // namespace WebCore
 
index 05b529c..d9bba86 100644 (file)
@@ -78,6 +78,8 @@ public:
     virtual TextTrackCue::CueType cueType() const OVERRIDE { return TextTrackCue::Generic; }
 
 private:
+    virtual bool isOrderedBefore(const TextTrackCue*) const OVERRIDE;
+
     TextTrackCueGeneric(ScriptExecutionContext*, double start, double end, const String&);
     
     Color m_foregroundColor;
index e8695af..f5451f5 100644 (file)
@@ -101,7 +101,7 @@ bool TextTrackCueList::add(PassRefPtr<TextTrackCue> prpCue, size_t start, size_t
     }
 
     size_t index = (start + end) / 2;
-    if (cue->startTime() < m_list[index]->startTime() || (cue->startTime() == m_list[index]->startTime() && cue->endTime() > m_list[index]->endTime()))
+    if (cue->isOrderedBefore(m_list[index].get()))
         return add(cue.release(), start, index);
 
     return add(cue.release(), index + 1, end);
index 26e57ff..2a2a98f 100644 (file)
@@ -321,20 +321,16 @@ void RenderTextTrackCue::repositionCueSnapToLinesSet()
 
 void RenderTextTrackCue::repositionGenericCue()
 {
-    TextTrackCueGeneric* cue = static_cast<TextTrackCueGeneric*>(m_cue);
-    if (!cue->useDefaultPosition())
-        return;
-
     ASSERT(firstChild());
-
+    ASSERT(m_cue->cueType() == TextTrackCue::WebVTT);
     InlineFlowBox* firstLineBox = toRenderInline(firstChild())->firstLineBox();
-    if (!firstLineBox)
-        return;
-
-    LayoutUnit parentWidth = containingBlock()->logicalWidth();
-    LayoutUnit width = firstLineBox->width();
-    LayoutUnit right = (parentWidth / 2) - (width / 2);
-    setX(right);
+    if (static_cast<TextTrackCueGeneric*>(m_cue)->useDefaultPosition() && firstLineBox) {
+        LayoutUnit parentWidth = containingBlock()->logicalWidth();
+        LayoutUnit width = firstLineBox->width();
+        LayoutUnit right = (parentWidth / 2) - (width / 2);
+        setX(right);
+    }
+    repositionCueSnapToLinesNotSet();
 }
 
 void RenderTextTrackCue::repositionCueSnapToLinesNotSet()