Support non-WebVTT cues from in-band text tracks
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 21 Jan 2013 22:02:19 +0000 (22:02 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 21 Jan 2013 22:02:19 +0000 (22:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=107046

Reviewed by Sam Weinig.

* CMakeLists.txt: Add new files.
* GNUmakefile.list.am: Ditto.
* Target.pri: Ditto.
* WebCore.gypi: Ditto.
* WebCore.vcproj/WebCore.vcproj: Ditto.
* WebCore.xcodeproj/project.pbxproj: Ditto.

* html/shadow/MediaControlElements.cpp:
(WebCore::MediaControlTextTrackContainerElement::updateDisplay): Pass video size to getDisplayTree.

* html/track/InbandTextTrack.cpp:
(WebCore::InbandTextTrack::addGenericCue): New, create a generic cue if it doesn't already exist.
(WebCore::InbandTextTrack::addWebVTTCue): Renamed from addCue.
* html/track/InbandTextTrack.h:

* html/track/TextTrack.cpp:
(WebCore::TextTrack::hasCue): Moved from InbandTextTrack.cpp, use operator == instead of inline
    comparison so derived TextTrackCues can be compared.
* html/track/TextTrack.h:

* html/track/TextTrackCue.cpp:
(WebCore::TextTrackCueBox::applyCSSProperties): Interface change.
(WebCore::TextTrackCue::TextTrackCue): Don't create the display tree in the constructor, it may
    never be needed.
(WebCore::TextTrackCue::createDisplayTree): New, create the display tree.
(WebCore::TextTrackCue::displayTreeInternal): Display tree accessor, allows it to be created lazily.
(WebCore::TextTrackCue::setAlign): Alignment -> CueAlignment.
(WebCore::TextTrackCue::setIsActive): Use displayTreeInternal().
(WebCore::TextTrackCue::getDisplayTree): Use displayTreeInternal(), pass video size to applyCSSProperties.
(WebCore::TextTrackCue::removeDisplayTree): Use displayTreeInternal().
(WebCore::TextTrackCue::operator==): New.
* html/track/TextTrackCue.h:
(WebCore::TextTrackCue::getAlignment): Alignment -> CueAlignment.
(WebCore::TextTrackCue::operator!=): New.
(WebCore::TextTrackCue::cueType): New, cue type identified needed by operator==.
(WebCore::TextTrackCue::ownerDocument): New.

* html/track/TextTrackCueGeneric.cpp: Added.
(WebCore::TextTrackCueGenericBox::create):
(WebCore::TextTrackCueGenericBox::TextTrackCueGenericBox):
(WebCore::TextTrackCueGenericBox::applyCSSProperties):
(WebCore:::TextTrackCue):
(WebCore::TextTrackCueGeneric::createDisplayTree):
(WebCore::TextTrackCueGeneric::operator==):
* html/track/TextTrackCueGeneric.h: Added.
(WebCore::TextTrackCueGeneric::create):
(WebCore::TextTrackCueGeneric::~TextTrackCueGeneric):
(WebCore::TextTrackCueGeneric::baseFontSizeRelativeToVideoHeight):
(WebCore::TextTrackCueGeneric::setBaseFontSizeRelativeToVideoHeight):
(WebCore::TextTrackCueGeneric::fontSizeMultiplier):
(WebCore::TextTrackCueGeneric::setFontSizeMultiplier):
(WebCore::TextTrackCueGeneric::fontName):
(WebCore::TextTrackCueGeneric::setFontName):
(WebCore::TextTrackCueGeneric::operator!=):
(WebCore::TextTrackCueGeneric::cueType):

* platform/graphics/InbandTextTrackPrivateClient.h:
* platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp:
(WebCore::InbandTextTrackPrivateAVF::processCueAttributes): Copy cue attributes into GenericCueData
    struct instead of trying to convert to WebVTT settings string. Process font size,font base
    size, font name, and vertical layout attributes,
(WebCore::InbandTextTrackPrivateAVF::processCue): Create separate cues for each attributed
    string in the array because each one can be at a different screen location.
(WebCore::InbandTextTrackPrivateAVF::resetCueValues):
* platform/graphics/avfoundation/InbandTextTrackPrivateAVF.h:
(InbandTextTrackPrivateAVF):

* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
(WebCore::MediaPlayerPrivateAVFoundation::seekCompleted): Reset any partially accumulated cues
    delivered since the seek was started.
(WebCore::MediaPlayerPrivateAVFoundation::addGenericCue): Renamed from flushCurrentCue.
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:

* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer): Whitespace cleanup.
(WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationObjC::tracksChanged): Tell legible output to deliver cues
    without any additional styling needed by the internal renderer.
(WebCore::MediaPlayerPrivateAVFoundationObjC::processTextTracks):
(WebCore::MediaPlayerPrivateAVFoundationObjC::setCurrentTrack): Do nothing if asked to change
    to the track that is already current.
(-[WebCoreAVFMovieObserver legibleOutput:didOutputAttributedStrings:nativeSampleBuffers:forItemTime:]):
    Check to make sure that the client callback isn't NULL.

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

23 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/shadow/MediaControlElements.cpp
Source/WebCore/html/track/InbandTextTrack.cpp
Source/WebCore/html/track/InbandTextTrack.h
Source/WebCore/html/track/TextTrack.cpp
Source/WebCore/html/track/TextTrack.h
Source/WebCore/html/track/TextTrackCue.cpp
Source/WebCore/html/track/TextTrackCue.h
Source/WebCore/html/track/TextTrackCueGeneric.cpp [new file with mode: 0644]
Source/WebCore/html/track/TextTrackCueGeneric.h [new file with mode: 0644]
Source/WebCore/platform/graphics/InbandTextTrackPrivateClient.h
Source/WebCore/platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp
Source/WebCore/platform/graphics/avfoundation/InbandTextTrackPrivateAVF.h
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm

index 2c7a5d6..a9c0dbc 100644 (file)
@@ -1581,6 +1581,7 @@ set(WebCore_SOURCES
     html/track/LoadableTextTrack.cpp
     html/track/TextTrack.cpp
     html/track/TextTrackCue.cpp
+    html/track/TextTrackCueGeneric.cpp
     html/track/TextTrackCueList.cpp
     html/track/TextTrackList.cpp
     html/track/TrackBase.cpp
index b1abc99..1926348 100644 (file)
@@ -1,3 +1,94 @@
+2013-01-21  Eric Carlson  <eric.carlson@apple.com>
+
+        Support non-WebVTT cues from in-band text tracks
+        https://bugs.webkit.org/show_bug.cgi?id=107046
+
+        Reviewed by Sam Weinig.
+
+        * CMakeLists.txt: Add new files.
+        * GNUmakefile.list.am: Ditto.
+        * Target.pri: Ditto.
+        * WebCore.gypi: Ditto.
+        * WebCore.vcproj/WebCore.vcproj: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+
+        * html/shadow/MediaControlElements.cpp:
+        (WebCore::MediaControlTextTrackContainerElement::updateDisplay): Pass video size to getDisplayTree.
+
+        * html/track/InbandTextTrack.cpp:
+        (WebCore::InbandTextTrack::addGenericCue): New, create a generic cue if it doesn't already exist.
+        (WebCore::InbandTextTrack::addWebVTTCue): Renamed from addCue.
+        * html/track/InbandTextTrack.h:
+
+        * html/track/TextTrack.cpp:
+        (WebCore::TextTrack::hasCue): Moved from InbandTextTrack.cpp, use operator == instead of inline
+            comparison so derived TextTrackCues can be compared.
+        * html/track/TextTrack.h:
+
+        * html/track/TextTrackCue.cpp:
+        (WebCore::TextTrackCueBox::applyCSSProperties): Interface change.
+        (WebCore::TextTrackCue::TextTrackCue): Don't create the display tree in the constructor, it may
+            never be needed.
+        (WebCore::TextTrackCue::createDisplayTree): New, create the display tree.
+        (WebCore::TextTrackCue::displayTreeInternal): Display tree accessor, allows it to be created lazily.
+        (WebCore::TextTrackCue::setAlign): Alignment -> CueAlignment.
+        (WebCore::TextTrackCue::setIsActive): Use displayTreeInternal().
+        (WebCore::TextTrackCue::getDisplayTree): Use displayTreeInternal(), pass video size to applyCSSProperties.
+        (WebCore::TextTrackCue::removeDisplayTree): Use displayTreeInternal().
+        (WebCore::TextTrackCue::operator==): New.
+        * html/track/TextTrackCue.h:
+        (WebCore::TextTrackCue::getAlignment): Alignment -> CueAlignment.
+        (WebCore::TextTrackCue::operator!=): New.
+        (WebCore::TextTrackCue::cueType): New, cue type identified needed by operator==.
+        (WebCore::TextTrackCue::ownerDocument): New.
+
+        * html/track/TextTrackCueGeneric.cpp: Added.
+        (WebCore::TextTrackCueGenericBox::create):
+        (WebCore::TextTrackCueGenericBox::TextTrackCueGenericBox):
+        (WebCore::TextTrackCueGenericBox::applyCSSProperties):
+        (WebCore:::TextTrackCue):
+        (WebCore::TextTrackCueGeneric::createDisplayTree):
+        (WebCore::TextTrackCueGeneric::operator==):
+        * html/track/TextTrackCueGeneric.h: Added.
+        (WebCore::TextTrackCueGeneric::create):
+        (WebCore::TextTrackCueGeneric::~TextTrackCueGeneric):
+        (WebCore::TextTrackCueGeneric::baseFontSizeRelativeToVideoHeight):
+        (WebCore::TextTrackCueGeneric::setBaseFontSizeRelativeToVideoHeight):
+        (WebCore::TextTrackCueGeneric::fontSizeMultiplier):
+        (WebCore::TextTrackCueGeneric::setFontSizeMultiplier):
+        (WebCore::TextTrackCueGeneric::fontName):
+        (WebCore::TextTrackCueGeneric::setFontName):
+        (WebCore::TextTrackCueGeneric::operator!=):
+        (WebCore::TextTrackCueGeneric::cueType):
+
+        * platform/graphics/InbandTextTrackPrivateClient.h:
+        * platform/graphics/avfoundation/InbandTextTrackPrivateAVF.cpp:
+        (WebCore::InbandTextTrackPrivateAVF::processCueAttributes): Copy cue attributes into GenericCueData
+            struct instead of trying to convert to WebVTT settings string. Process font size,font base
+            size, font name, and vertical layout attributes,
+        (WebCore::InbandTextTrackPrivateAVF::processCue): Create separate cues for each attributed
+            string in the array because each one can be at a different screen location.
+        (WebCore::InbandTextTrackPrivateAVF::resetCueValues):
+        * platform/graphics/avfoundation/InbandTextTrackPrivateAVF.h:
+        (InbandTextTrackPrivateAVF):
+
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundation::seekCompleted): Reset any partially accumulated cues
+            delivered since the seek was started.
+        (WebCore::MediaPlayerPrivateAVFoundation::addGenericCue): Renamed from flushCurrentCue.
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
+
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer): Whitespace cleanup.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem): Ditto.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::tracksChanged): Tell legible output to deliver cues
+            without any additional styling needed by the internal renderer.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::processTextTracks):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::setCurrentTrack): Do nothing if asked to change
+            to the track that is already current.
+        (-[WebCoreAVFMovieObserver legibleOutput:didOutputAttributedStrings:nativeSampleBuffers:forItemTime:]):
+            Check to make sure that the client callback isn't NULL.
+
 2013-01-21  Robert Hogan  <robert@webkit.org>
 
         Misaligned logo on www.nzherald.co.nz possibly due to negative margin-top
index 078f57f..40e9b46 100644 (file)
@@ -3672,6 +3672,8 @@ webcore_sources += \
        Source/WebCore/html/track/TextTrack.h \
        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/html/track/TextTrackCueList.h \
        Source/WebCore/html/track/TextTrackList.cpp \
index 09cca80..cf70203 100644 (file)
@@ -1915,6 +1915,7 @@ HEADERS += \
     html/track/LoadableTextTrack.h \
     html/track/TextTrack.h \
     html/track/TextTrackCue.h \
+    html/track/TextTrackCueGeneric.h \
     html/track/TextTrackCueList.h \
     html/track/TextTrackList.h \
     html/track/TrackBase.h \
index a700dd6..e46b816 100644 (file)
             'html/track/TextTrack.h',
             'html/track/TextTrackCue.cpp',
             'html/track/TextTrackCue.h',
+            'html/track/TextTrackCueGeneric.cpp',
+            'html/track/TextTrackCueGeneric.h',
             'html/track/TextTrackCueList.cpp',
             'html/track/TextTrackCueList.h',
             'html/track/TextTrackList.cpp',
index 2ce856b..c25df2e 100755 (executable)
                                        >
                                </File>
                                <File
+                                       RelativePath="..\html\track\TextTrackCueGeneric.cpp"
+                                       >
+                               </File>
+                               <File
+                                       RelativePath="..\html\track\TextTrackCueGeneric.h"
+                                       >
+                               </File>
+                               <File
                                        RelativePath="..\html\track\TextTrackCueList.cpp"
                                        >
                                </File>
index 6a5bb54..9eaf6ef 100644 (file)
                070756DF14239B4E00414161 /* JSTextTrackCueList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 070756D914239B4C00414161 /* JSTextTrackCueList.cpp */; };
                070756E014239B4E00414161 /* JSTextTrackCueList.h in Headers */ = {isa = PBXBuildFile; fileRef = 070756DA14239B4E00414161 /* JSTextTrackCueList.h */; };
                0709FC4E1025DEE30059CDBA /* AccessibilitySlider.h in Headers */ = {isa = PBXBuildFile; fileRef = 0709FC4D1025DEE30059CDBA /* AccessibilitySlider.h */; };
+               071A9EC2168FBC43002629F9 /* TextTrackCueGeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 071A9EC0168FB56C002629F9 /* TextTrackCueGeneric.cpp */; };
+               071A9EC3168FBC55002629F9 /* TextTrackCueGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 071A9EC1168FB56C002629F9 /* TextTrackCueGeneric.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0720B0A014D3323500642955 /* GenericEventQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0720B09E14D3323500642955 /* GenericEventQueue.cpp */; };
                0720B0A014D3323500642956 /* GestureEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0720B09F14D3323500642956 /* GestureEvent.cpp */; };
                0720B0A114D3323500642955 /* GenericEventQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0720B09F14D3323500642955 /* GenericEventQueue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                070756DA14239B4E00414161 /* JSTextTrackCueList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTextTrackCueList.h; sourceTree = "<group>"; };
                0709FC4D1025DEE30059CDBA /* AccessibilitySlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilitySlider.h; sourceTree = "<group>"; };
                070DD8F50F01868000727DEB /* mediaControls.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mediaControls.css; sourceTree = "<group>"; };
+               071A9EC0168FB56C002629F9 /* TextTrackCueGeneric.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextTrackCueGeneric.cpp; sourceTree = "<group>"; };
+               071A9EC1168FB56C002629F9 /* TextTrackCueGeneric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextTrackCueGeneric.h; sourceTree = "<group>"; };
                0720B09E14D3323500642955 /* GenericEventQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericEventQueue.cpp; sourceTree = "<group>"; };
                0720B09F14D3323500642955 /* GenericEventQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericEventQueue.h; sourceTree = "<group>"; };
                0720B09F14D3323500642956 /* GestureEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GestureEvent.cpp; sourceTree = "<group>"; };
                                9759E93814EF1CF80026A2DD /* TextTrackCue.cpp */,
                                9759E93914EF1CF80026A2DD /* TextTrackCue.h */,
                                9759E93A14EF1CF80026A2DD /* TextTrackCue.idl */,
+                               071A9EC0168FB56C002629F9 /* TextTrackCueGeneric.cpp */,
+                               071A9EC1168FB56C002629F9 /* TextTrackCueGeneric.h */,
                                9759E93B14EF1CF80026A2DD /* TextTrackCueList.cpp */,
                                9759E93C14EF1CF80026A2DD /* TextTrackCueList.h */,
                                9759E93D14EF1CF80026A2DD /* TextTrackCueList.idl */,
                                B2C3DA4B0D006C1D00EF6F26 /* TextStream.h in Headers */,
                                9759E94014EF1CF80026A2DD /* TextTrack.h in Headers */,
                                9759E94314EF1CF80026A2DD /* TextTrackCue.h in Headers */,
+                               071A9EC3168FBC55002629F9 /* TextTrackCueGeneric.h in Headers */,
                                9759E94614EF1CF80026A2DD /* TextTrackCueList.h in Headers */,
                                076970871463AD8700F502CF /* TextTrackList.h in Headers */,
                                B1AD4E7413A12A4600846B27 /* TextTrackLoader.h in Headers */,
                                B2C3DA4A0D006C1D00EF6F26 /* TextStream.cpp in Sources */,
                                9759E93F14EF1CF80026A2DD /* TextTrack.cpp in Sources */,
                                9759E94214EF1CF80026A2DD /* TextTrackCue.cpp in Sources */,
+                               071A9EC2168FBC43002629F9 /* TextTrackCueGeneric.cpp in Sources */,
                                9759E94514EF1CF80026A2DD /* TextTrackCueList.cpp in Sources */,
                                076970861463AD8700F502CF /* TextTrackList.cpp in Sources */,
                                B1AD4E7313A12A4600846B27 /* TextTrackLoader.cpp in Sources */,
index 2abd938..9cceef3 100644 (file)
@@ -3819,6 +3819,11 @@ void HTMLMediaElement::clearMediaPlayer(int flags)
 
     m_pendingLoadFlags &= ~flags;
     m_loadState = WaitingForSource;
+
+#if ENABLE(VIDEO_TRACK)
+    if (m_textTracks)
+        configureTextTrackDisplay();
+#endif
 }
 
 bool HTMLMediaElement::canSuspend() const
index 2934496..06e2f6e 100644 (file)
@@ -1304,8 +1304,7 @@ void MediaControlTextTrackContainerElement::updateDisplay()
         if (!cue->track() || !cue->track()->isRendered())
             continue;
 
-        RefPtr<TextTrackCueBox> displayBox = cue->getDisplayTree();
-
+        RefPtr<TextTrackCueBox> displayBox = cue->getDisplayTree(m_videoDisplaySize.size());
         if (displayBox->hasChildNodes() && !contains(static_cast<Node*>(displayBox.get())))
             // Note: the display tree of a cue is removed when the active flag of the cue is unset.
             m_cueContainer->appendChild(displayBox, ASSERT_NO_EXCEPTION, false);
index 4454c8d..bfd96c0 100644 (file)
 #include "Document.h"
 #include "Event.h"
 #include "InbandTextTrackPrivate.h"
+#include "Logging.h"
 #include "MediaPlayer.h"
+#include "TextTrackCueGeneric.h"
 #include "TextTrackCueList.h"
-
+#include <math.h>
 #include <wtf/UnusedParam.h>
 
 namespace WebCore {
@@ -98,74 +100,55 @@ size_t InbandTextTrack::inbandTrackIndex()
     return m_private->textTrackIndex();
 }
 
-void InbandTextTrack::addCue(InbandTextTrackPrivate* trackPrivate, double start, double end, const String& id, const String& content, const String& settings)
+void InbandTextTrack::addGenericCue(InbandTextTrackPrivate* trackPrivate, GenericCueData* cueData)
 {
     UNUSED_PARAM(trackPrivate);
     ASSERT(trackPrivate == m_private);
 
-    RefPtr<TextTrackCue> cue = TextTrackCue::create(scriptExecutionContext(), start, end, content);
-    cue->setId(id);
-    cue->setCueSettings(settings);
-    cue->setTrack(this);
+    RefPtr<TextTrackCueGeneric> cue = TextTrackCueGeneric::create(scriptExecutionContext(), cueData->startTime(), cueData->endTime(), cueData->content());
+
+    cue->setId(cueData->id());
+    cue->setBaseFontSizeRelativeToVideoHeight(cueData->baseFontSize());
+    cue->setFontSizeMultiplier(cueData->relativeFontSize());
+    cue->setFontName(cueData->fontName());
+
+    ExceptionCode ec;
+    if (cueData->position() > 0)
+        cue->setPosition(lround(cueData->position()), ec);
+    if (cueData->line() > 0)
+        cue->setLine(lround(cueData->line()), ec);
+    if (cueData->size() > 0)
+        cue->setSize(lround(cueData->size()), ec);
+    if (cueData->align() == GenericCueData::Start)
+        cue->setAlign(ASCIILiteral("start"), ec);
+    else if (cueData->align() == GenericCueData::Middle)
+        cue->setAlign(ASCIILiteral("middle"), ec);
+    else if (cueData->align() == GenericCueData::End)
+        cue->setAlign(ASCIILiteral("end"), ec);
+    cue->setSnapToLines(false);
+
+    if (hasCue(cue.get())) {
+        LOG(Media, "InbandTextTrack::addGenericCue ignoring already added cue: start=%.2f, end=%.2f, content=\"%s\"\n",
+            cueData->startTime(), cueData->endTime(), cueData->content().utf8().data());
+        return;
+    }
 
-    if (!m_cues)
-        m_cues = TextTrackCueList::create();
-    m_cues->add(cue);
-    
-    if (client())
-        client()->textTrackAddCues(this, m_cues.get());
+    addCue(cue);
 }
 
-bool InbandTextTrack::hasCue(InbandTextTrackPrivate*, double startTime, double endTime, const String& id, const String& content, const String& settings)
+void InbandTextTrack::addWebVTTCue(InbandTextTrackPrivate* trackPrivate, double start, double end, const String& id, const String& content, const String& settings)
 {
+    UNUSED_PARAM(trackPrivate);
+    ASSERT(trackPrivate == m_private);
 
-    if (startTime < 0 || endTime < 0)
-        return false;
-
-    if (!cues()->length())
-        return false;
-
-    size_t searchStart = 0;
-    size_t searchEnd = cues()->length();
-
-    while (1) {
-        ASSERT(searchStart <= cues()->length());
-        ASSERT(searchEnd <= cues()->length());
-        
-        TextTrackCue* cue;
-        
-        // Cues in the TextTrackCueList are maintained in start time order.
-        if (searchStart == searchEnd) {
-            if (!searchStart)
-                return false;
-            
-            cue = cues()->item(searchStart - 1);
-            if (!cue)
-                return false;
-            if (cue->startTime() != startTime)
-                return false;
-            if (cue->endTime() != endTime)
-                return false;
-            if (cue->text() != content)
-                return false;
-            if (cue->cueSettings() != settings)
-                return false;
-            if (cue->id() != id)
-                return false;
-            
-            return true;
-        }
-        
-        size_t index = (searchStart + searchEnd) / 2;
-        cue = cues()->item(index);
-        if (startTime < cue->startTime() || (startTime == cue->startTime() && endTime > cue->endTime()))
-            searchEnd = index;
-        else
-            searchStart = index + 1;
-    }
+    RefPtr<TextTrackCue> cue = TextTrackCue::create(scriptExecutionContext(), start, end, content);
+    cue->setId(id);
+    cue->setCueSettings(settings);
     
-    ASSERT_NOT_REACHED();
-    return false;
+    if (hasCue(cue.get()))
+        return;
+
+    addCue(cue);
 }
 
 } // namespace WebCore
index ebf78b7..55c1791 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -51,8 +51,8 @@ public:
 private:
     InbandTextTrack(ScriptExecutionContext*, TextTrackClient*, PassRefPtr<InbandTextTrackPrivate>);
 
-    virtual void addCue(InbandTextTrackPrivate*, double, double, const String&, const String&, const String&) OVERRIDE;
-    virtual bool hasCue(InbandTextTrackPrivate*, double, double, const String&, const String&, const String&) OVERRIDE;
+    virtual void addGenericCue(InbandTextTrackPrivate*, GenericCueData*) OVERRIDE;
+    virtual void addWebVTTCue(InbandTextTrackPrivate*, double, double, const String&, const String&, const String&) OVERRIDE;
 
     RefPtr<InbandTextTrackPrivate> m_private;
 };
index 10b605c..89c16d5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc.  All rights reserved.
- * Copyright (C) 2011 Apple Inc.  All rights reserved.
+ * Copyright (C) 2011, 2012, 2013 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -339,6 +339,64 @@ int TextTrack::trackIndexRelativeToRenderedTracks()
     return m_renderedTrackIndex;
 }
 
+bool TextTrack::hasCue(TextTrackCue* cue)
+{
+    if (cue->startTime() < 0 || cue->endTime() < 0)
+        return false;
+    
+    if (!m_cues || !m_cues->length())
+        return false;
+    
+    size_t searchStart = 0;
+    size_t searchEnd = m_cues->length();
+    
+    while (1) {
+        ASSERT(searchStart <= m_cues->length());
+        ASSERT(searchEnd <= m_cues->length());
+        
+        TextTrackCue* existingCue;
+        
+        // Cues in the TextTrackCueList are maintained in start time order.
+        if (searchStart == searchEnd) {
+            if (!searchStart)
+                return false;
+
+            // If there is more than one cue with the same start time, back up to first one so we
+            // consider all of them.
+            while (searchStart >= 2 && cue->startTime() == m_cues->item(searchStart - 2)->startTime())
+                --searchStart;
+            
+            bool firstCompare = true;
+            while (1) {
+                if (!firstCompare)
+                    ++searchStart;
+                firstCompare = false;
+                if (searchStart > m_cues->length())
+                    return false;
+
+                existingCue = m_cues->item(searchStart - 1);
+                if (!existingCue || cue->startTime() > existingCue->startTime())
+                    return false;
+
+                if (*existingCue != *cue)
+                    continue;
+                
+                return true;
+            }
+        }
+        
+        size_t index = (searchStart + searchEnd) / 2;
+        existingCue = m_cues->item(index);
+        if (cue->startTime() < existingCue->startTime() || (cue->startTime() == existingCue->startTime() && cue->endTime() > existingCue->endTime()))
+            searchEnd = index;
+        else
+            searchStart = index + 1;
+    }
+    
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
 } // namespace WebCore
 
 #endif
index 18ea62a..37e753c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc. All rights reserved.
- * Copyright (C) 2011, 2012 Apple Inc.  All rights reserved.
+ * Copyright (C) 2011, 2012, 2013 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -99,6 +99,7 @@ public:
 
     void addCue(PassRefPtr<TextTrackCue>);
     void removeCue(TextTrackCue*, ExceptionCode&);
+    bool hasCue(TextTrackCue*);
 
     void cueWillChange(TextTrackCue*);
     void cueDidChange(TextTrackCue*);
index a12ff23..3845a74 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc.  All rights reserved.
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -107,7 +107,7 @@ TextTrackCue* TextTrackCueBox::getCue() const
     return m_cue;
 }
 
-void TextTrackCueBox::applyCSSProperties()
+void TextTrackCueBox::applyCSSProperties(const IntSize&)
 {
     // FIXME: Apply all the initial CSS positioning properties. http://wkb.ug/79916
 
@@ -210,7 +210,6 @@ TextTrackCue::TextTrackCue(ScriptExecutionContext* context, double start, double
     , m_snapToLines(true)
     , m_allDocumentNodes(HTMLDivElement::create(static_cast<Document*>(context)))
     , m_displayTreeShouldChange(true)
-    , m_displayTree(TextTrackCueBox::create(static_cast<Document*>(m_scriptExecutionContext), this))
 {
     ASSERT(m_scriptExecutionContext->isDocument());
 
@@ -228,6 +227,18 @@ TextTrackCue::~TextTrackCue()
 {
 }
 
+PassRefPtr<TextTrackCueBox> TextTrackCue::createDisplayTree()
+{
+    return TextTrackCueBox::create(ownerDocument(), this);
+}
+
+PassRefPtr<TextTrackCueBox> TextTrackCue::displayTreeInternal()
+{
+    if (!m_displayTree)
+        m_displayTree = createDisplayTree();
+    return m_displayTree;
+}
+
 void TextTrackCue::cueWillChange()
 {
     if (m_track)
@@ -438,7 +449,7 @@ void TextTrackCue::setAlign(const String& value, ExceptionCode& ec)
     // match for the new value, if any. If none of the values match, then the user
     // agent must instead throw a SyntaxError exception.
     
-    Alignment alignment = m_cueAlignment;
+    CueAlignment alignment = m_cueAlignment;
     if (value == startKeyword())
         alignment = Start;
     else if (value == middleKeyword())
@@ -545,8 +556,7 @@ void TextTrackCue::setIsActive(bool active)
 
     if (!active) {
         // Remove the display tree as soon as the cue becomes inactive.
-        ExceptionCode ec;
-        m_displayTree->remove(ec);
+        displayTreeInternal()->remove(ASSERT_NO_EXCEPTION);
     }
 }
 
@@ -722,10 +732,11 @@ void TextTrackCue::updateDisplayTree(float movieTime)
     m_allDocumentNodes->appendChild(referenceTree);
 }
 
-PassRefPtr<TextTrackCueBox> TextTrackCue::getDisplayTree()
+PassRefPtr<TextTrackCueBox> TextTrackCue::getDisplayTree(const IntSize& videoSize)
 {
+    RefPtr<TextTrackCueBox> displayTree = displayTreeInternal();
     if (!m_displayTreeShouldChange || !track()->isRendered())
-        return m_displayTree;
+        return displayTree;
 
     // 10.1 - 10.10
     calculateDisplayParameters();
@@ -733,7 +744,7 @@ PassRefPtr<TextTrackCueBox> TextTrackCue::getDisplayTree()
     // 10.11. Apply the terms of the CSS specifications to nodes within the
     // following constraints, thus obtaining a set of CSS boxes positioned
     // relative to an initial containing block:
-    m_displayTree->removeChildren();
+    displayTree->removeChildren();
 
     // The document tree is the tree of WebVTT Node Objects rooted at nodes.
 
@@ -743,7 +754,7 @@ PassRefPtr<TextTrackCueBox> TextTrackCue::getDisplayTree()
 
     // Note: This is contained by default in m_allDocumentNodes.
     m_allDocumentNodes->setPseudo(allNodesShadowPseudoId());
-    m_displayTree->appendChild(m_allDocumentNodes, ASSERT_NO_EXCEPTION, true);
+    displayTree->appendChild(m_allDocumentNodes, ASSERT_NO_EXCEPTION, true);
 
     // FIXME(BUG 79916): Runs of children of WebVTT Ruby Objects that are not
     // WebVTT Ruby Text Objects must be wrapped in anonymous boxes whose
@@ -756,18 +767,18 @@ PassRefPtr<TextTrackCueBox> TextTrackCue::getDisplayTree()
     // is no line breaking opportunity. (Thus, normally text wraps as needed,
     // but if there is a particularly long word, it does not overflow as it
     // normally would in CSS, it is instead forcibly wrapped at the box's edge.)
-    m_displayTree->applyCSSProperties();
+    displayTree->applyCSSProperties(videoSize);
 
     m_displayTreeShouldChange = false;
 
     // 10.15. Let cue's text track cue display state have the CSS boxes in
     // boxes.
-    return m_displayTree;
+    return displayTree;
 }
 
 void TextTrackCue::removeDisplayTree()
 {
-    m_displayTree->remove(ASSERT_NO_EXCEPTION);
+    displayTreeInternal()->remove(ASSERT_NO_EXCEPTION);
 }
 
 std::pair<double, double> TextTrackCue::getPositionCoordinates() const
@@ -1066,6 +1077,33 @@ EventTargetData* TextTrackCue::ensureEventTargetData()
     return &m_eventTargetData;
 }
 
+bool TextTrackCue::operator==(const TextTrackCue& cue) const
+{
+    if (cueType() != cue.cueType())
+        return false;
+
+    if (m_endTime != cue.endTime())
+        return false;
+    if (m_startTime != cue.startTime())
+        return false;
+    if (m_content != cue.text())
+        return false;
+    if (m_settings != cue.cueSettings())
+        return false;
+    if (m_id != cue.id())
+        return false;
+    if (m_textPosition != cue.position())
+        return false;
+    if (m_linePosition != cue.line())
+        return false;
+    if (m_cueSize != cue.size())
+        return false;
+    if (align() != cue.align())
+        return false;
+    
+    return true;
+}
+
 } // namespace WebCore
 
 #endif
index ef3d804..23b27ce 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc.  All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -57,11 +58,11 @@ public:
     }
 
     TextTrackCue* getCue() const;
-    void applyCSSProperties();
+    virtual void applyCSSProperties(const IntSize& videoSize);
 
     static const AtomicString& textTrackCueBoxShadowPseudoId();
 
-private:
+protected:
     TextTrackCueBox(Document*, TextTrackCue*);
 
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
@@ -122,13 +123,13 @@ public:
     void setSnapToLines(bool);
 
     int line() const { return m_linePosition; }
-    void setLine(int, ExceptionCode&);
+    virtual void setLine(int, ExceptionCode&);
 
     int position() const { return m_textPosition; }
-    void setPosition(int, ExceptionCode&);
+    virtual void setPosition(int, ExceptionCode&);
 
     int size() const { return m_cueSize; }
-    void setSize(int, ExceptionCode&);
+    virtual void setSize(int, ExceptionCode&);
 
     const String& align() const;
     void setAlign(const String&, ExceptionCode&);
@@ -151,7 +152,7 @@ public:
     bool isActive();
     void setIsActive(bool);
 
-    PassRefPtr<TextTrackCueBox> getDisplayTree();
+    PassRefPtr<TextTrackCueBox> getDisplayTree(const IntSize& videoSize);
     void updateDisplayTree(float);
     void removeDisplayTree();
     void markFutureAndPastNodes(ContainerNode*, double, double);
@@ -173,6 +174,25 @@ public:
     };
     WritingDirection getWritingDirection() const { return m_writingDirection; }
 
+    enum CueAlignment {
+        Start,
+        Middle,
+        End
+    };
+    CueAlignment getAlignment() const { return m_cueAlignment; }
+
+    virtual bool operator==(const TextTrackCue&) const;
+    virtual bool operator!=(const TextTrackCue& cue) const
+    {
+        return !(*this == cue);
+    }
+    
+    enum CueType {
+        Generic,
+        WebVTT
+    };
+    virtual CueType cueType() const { return WebVTT; }
+
     DEFINE_ATTRIBUTE_EVENT_LISTENER(enter);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(exit);
 
@@ -183,9 +203,14 @@ protected:
     virtual EventTargetData* eventTargetData();
     virtual EventTargetData* ensureEventTargetData();
 
-private:
     TextTrackCue(ScriptExecutionContext*, double start, double end, const String& content);
 
+    Document* ownerDocument() { return static_cast<Document*>(m_scriptExecutionContext); }
+
+    virtual PassRefPtr<TextTrackCueBox> createDisplayTree();
+    PassRefPtr<TextTrackCueBox> displayTreeInternal();
+
+private:
     std::pair<double, double> getPositionCoordinates() const;
     void parseSettings(const String&);
 
@@ -213,8 +238,7 @@ private:
 
     WritingDirection m_writingDirection;
 
-    enum Alignment { Start, Middle, End };
-    Alignment m_cueAlignment;
+    CueAlignment m_cueAlignment;
 
     RefPtr<DocumentFragment> m_webVTTNodeTree;
     TextTrack* m_track;
diff --git a/Source/WebCore/html/track/TextTrackCueGeneric.cpp b/Source/WebCore/html/track/TextTrackCueGeneric.cpp
new file mode 100644 (file)
index 0000000..e736543
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO_TRACK)
+
+#include "TextTrackCueGeneric.h"
+
+#include "CSSPropertyNames.h"
+#include "CSSValueKeywords.h"
+#include "HTMLDivElement.h"
+#include "HTMLNames.h"
+#include "InbandTextTrackPrivateClient.h"
+#include "RenderObject.h"
+#include "RenderTextTrackCue.h"
+#include "ScriptExecutionContext.h"
+#include "TextTrackCue.h"
+
+namespace WebCore {
+
+class TextTrackCueGenericBoxElement : public TextTrackCueBox {
+public:
+    static PassRefPtr<TextTrackCueGenericBoxElement> create(Document* document, TextTrackCueGeneric* cue)
+    {
+        return adoptRef(new TextTrackCueGenericBoxElement(document, cue));
+    }
+    
+    virtual void applyCSSProperties(const IntSize&) OVERRIDE;
+    
+private:
+    TextTrackCueGenericBoxElement(Document*, TextTrackCue*);
+};
+
+TextTrackCueGenericBoxElement::TextTrackCueGenericBoxElement(Document* document, TextTrackCue* cue)
+    : TextTrackCueBox(document, cue)
+{
+}
+
+void TextTrackCueGenericBoxElement::applyCSSProperties(const IntSize& videoSize)
+{
+    setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute);
+    setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext);
+    
+    TextTrackCueGeneric* cue = static_cast<TextTrackCueGeneric*>(getCue());
+
+    if (cue->useDefaultPosition()) {
+        setInlineStyleProperty(CSSPropertyBottom, "0");
+        setInlineStyleProperty(CSSPropertyMarginBottom, 1.0, CSSPrimitiveValue::CSS_PERCENTAGE);
+    } else {
+        setInlineStyleProperty(CSSPropertyLeft, static_cast<float>(cue->position()), CSSPrimitiveValue::CSS_PERCENTAGE);
+        setInlineStyleProperty(CSSPropertyTop, static_cast<float>(cue->line()), CSSPrimitiveValue::CSS_PERCENTAGE);
+    }
+
+    float size = static_cast<float>(cue->getCSSSize());
+    if (cue->getWritingDirection() == TextTrackCue::Horizontal) {
+        setInlineStyleProperty(CSSPropertyDirection, CSSValueLtr);
+        setInlineStyleProperty(CSSPropertyWidth, size, CSSPrimitiveValue::CSS_PERCENTAGE);
+        setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto);
+    } else {
+        setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto);
+        setInlineStyleProperty(CSSPropertyHeight, size,  CSSPrimitiveValue::CSS_PERCENTAGE);
+    }
+
+    if (cue->baseFontSizeRelativeToVideoHeight()) {
+        double fontSize = videoSize.height() * cue->baseFontSizeRelativeToVideoHeight() / 100;
+        if (cue->fontSizeMultiplier())
+            fontSize *= cue->fontSizeMultiplier() / 100;
+        setInlineStyleProperty(CSSPropertyFontSize, String::number(fontSize) + "px");
+    }
+
+    if (cue->getAlignment() == TextTrackCue::Start)
+        setInlineStyleProperty(CSSPropertyTextAlign, CSSValueStart);
+    else if (cue->getAlignment() == TextTrackCue::End)
+        setInlineStyleProperty(CSSPropertyTextAlign, CSSValueEnd);
+    else
+        setInlineStyleProperty(CSSPropertyTextAlign, CSSValueCenter);
+
+    setInlineStyleProperty(CSSPropertyWebkitWritingMode, cue->getCSSWritingMode(), false);
+    setInlineStyleProperty(CSSPropertyWhiteSpace, CSSValuePreWrap);
+    setInlineStyleProperty(CSSPropertyWordBreak, CSSValueNormal);
+}
+
+TextTrackCueGeneric::TextTrackCueGeneric(ScriptExecutionContext* context, double start, double end, const String& content)
+    : TextTrackCue(context, start, end, content)
+    , m_baseFontSizeRelativeToVideoHeight(0)
+    , m_fontSizeMultiplier(0)
+    , m_defaultPosition(true)
+{
+}
+
+PassRefPtr<TextTrackCueBox> TextTrackCueGeneric::createDisplayTree()
+{
+    return TextTrackCueGenericBoxElement::create(ownerDocument(), this);
+}
+
+void TextTrackCueGeneric::setLine(int line, ExceptionCode& ec)
+{
+    m_defaultPosition = false;
+    TextTrackCue::setLine(line, ec);
+}
+
+void TextTrackCueGeneric::setPosition(int position, ExceptionCode& ec)
+{
+    m_defaultPosition = false;
+    TextTrackCue::setPosition(position, ec);
+}
+
+bool TextTrackCueGeneric::operator==(const TextTrackCue& cue) const
+{
+    if (cue.cueType() != TextTrackCue::Generic)
+        return false;
+
+    const TextTrackCueGeneric* other = static_cast<const TextTrackCueGeneric*>(&cue);
+
+    if (m_baseFontSizeRelativeToVideoHeight != other->baseFontSizeRelativeToVideoHeight())
+        return false;
+    if (m_fontSizeMultiplier != other->fontSizeMultiplier())
+        return false;
+    if (m_fontName != other->fontName())
+        return false;
+
+    return TextTrackCue::operator==(cue);
+}
+    
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/html/track/TextTrackCueGeneric.h b/Source/WebCore/html/track/TextTrackCueGeneric.h
new file mode 100644 (file)
index 0000000..2f4e802
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TextTrackCueGeneric_h
+#define TextTrackCueGeneric_h
+
+#if ENABLE(VIDEO_TRACK)
+
+#include "HTMLElement.h"
+#include "TextTrackCue.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class GenericCueData;
+
+// A "generic" cue is a non-WebVTT cue, so it is not positioned/sized with the WebVTT logic.
+class TextTrackCueGeneric : public TextTrackCue {
+public:
+    static PassRefPtr<TextTrackCueGeneric> create(ScriptExecutionContext* context, double start, double end, const String& content)
+    {
+        return adoptRef(new TextTrackCueGeneric(context, start, end, content));
+    }
+    
+    virtual ~TextTrackCueGeneric() { }
+
+    virtual PassRefPtr<TextTrackCueBox> createDisplayTree() OVERRIDE;
+
+    virtual void setLine(int, ExceptionCode&) OVERRIDE;
+    virtual void setPosition(int, ExceptionCode&) OVERRIDE;
+
+    bool useDefaultPosition() const { return m_defaultPosition; }
+    
+    double baseFontSizeRelativeToVideoHeight() const { return m_baseFontSizeRelativeToVideoHeight; }
+    void setBaseFontSizeRelativeToVideoHeight(double size) { m_baseFontSizeRelativeToVideoHeight = size; }
+
+    double fontSizeMultiplier() const { return m_fontSizeMultiplier; }
+    void setFontSizeMultiplier(double size) { m_fontSizeMultiplier = size; }
+
+    String fontName() const { return m_fontName; }
+    void setFontName(String name) { m_fontName = name; }
+
+    virtual bool operator==(const TextTrackCue&) const OVERRIDE;
+    virtual bool operator!=(const TextTrackCue& cue) const OVERRIDE
+    {
+        return !(*this == cue);
+    }
+
+    virtual TextTrackCue::CueType cueType() const OVERRIDE { return TextTrackCue::Generic; }
+
+private:
+    TextTrackCueGeneric(ScriptExecutionContext*, double start, double end, const String&);
+    
+    double m_baseFontSizeRelativeToVideoHeight;
+    double m_fontSizeMultiplier;
+    String m_fontName;
+    bool m_defaultPosition;
+};
+
+} // namespace WebCore
+
+#endif
+#endif
index 3d47db4..83e92d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
 #ifndef InbandTextTrackPrivateClient_h
 #define InbandTextTrackPrivateClient_h
 
+#include <wtf/Noncopyable.h>
 #include <wtf/text/WTFString.h>
 
 #if ENABLE(VIDEO_TRACK)
@@ -34,12 +35,81 @@ namespace WebCore {
 
 class InbandTextTrackPrivate;
 
+class GenericCueData {
+    WTF_MAKE_NONCOPYABLE(GenericCueData); WTF_MAKE_FAST_ALLOCATED;
+public:
+    GenericCueData()
+        : m_startTime(0)
+        , m_endTime(0)
+        , m_line(-1)
+        , m_position(-1)
+        , m_size(-1)
+        , m_align(None)
+        , m_baseFontSize(0)
+        , m_relativeFontSize(0)
+    {
+    }
+    virtual ~GenericCueData() { }
+
+    double startTime() const { return m_startTime; }
+    void setStartTime(double startTime) { m_startTime = startTime; }
+
+    double endTime() const { return m_endTime; }
+    void setEndTime(double endTime) { m_endTime = endTime; }
+
+    String id() const { return m_id; }
+    void setId(String id) { m_id = id; }
+
+    String content() const { return m_content; }
+    void setContent(String content) { m_content = content; }
+
+    double line() const { return m_line; }
+    void setLine(double line) { m_line = line; }
+
+    double position() const { return m_position; }
+    void setPosition(double position) { m_position = position; }
+
+    double size() const { return m_size; }
+    void setSize(double size) { m_size = size; }
+
+    enum Alignment {
+        None,
+        Start,
+        Middle,
+        End
+    };
+    Alignment align() const { return m_align; }
+    void setAlign(Alignment align) { m_align = align; }
+
+    String fontName() const { return m_fontName; }
+    void setFontName(String fontName) { m_fontName = fontName; }
+
+    double baseFontSize() const { return m_baseFontSize; }
+    void setBaseFontSize(double baseFontSize) { m_baseFontSize = baseFontSize; }
+
+    double relativeFontSize() const { return m_relativeFontSize; }
+    void setRelativeFontSize(double relativeFontSize) { m_relativeFontSize = relativeFontSize; }
+    
+private:
+    double m_startTime;
+    double m_endTime;
+    String m_id;
+    String m_content;
+    double m_line;
+    double m_position;
+    double m_size;
+    Alignment m_align;
+    String m_fontName;
+    double m_baseFontSize;
+    double m_relativeFontSize;
+};
+
 class InbandTextTrackPrivateClient {
 public:
     virtual ~InbandTextTrackPrivateClient() { }
     
-    virtual void addCue(InbandTextTrackPrivate*, double /*start*/, double /*end*/, const String& /*id*/, const String& /*content*/, const String& /*settings*/) = 0;
-    virtual bool hasCue(InbandTextTrackPrivate*, double /*start*/, double /*end*/, const String& /*id*/, const String& /*content*/, const String& /*settings*/) = 0;
+    virtual void addWebVTTCue(InbandTextTrackPrivate*, double /*start*/, double /*end*/, const String& /*id*/, const String& /*content*/, const String& /*settings*/) = 0;
+    virtual void addGenericCue(InbandTextTrackPrivate*, GenericCueData*) = 0;
 };
 
 } // namespace WebCore
index 4688094..7409e5a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
 
 #include "InbandTextTrackPrivateAVF.h"
 
+#include "InbandTextTrackPrivateClient.h"
 #include "Logging.h"
 #include "MediaPlayerPrivateAVFoundation.h"
 #include "SoftLinking.h"
@@ -36,6 +37,7 @@
 #include <wtf/UnusedParam.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/WTFString.h>
+#include <wtf/unicode/CharacterNames.h>
 
 SOFT_LINK_FRAMEWORK_OPTIONAL(CoreMedia)
 
@@ -52,6 +54,9 @@ SOFT_LINK_POINTER_OPTIONAL(CoreMedia, kCMTextMarkupAttribute_OrthogonalLinePosit
 SOFT_LINK_POINTER_OPTIONAL(CoreMedia, kCMTextMarkupAttribute_VerticalLayout, CFStringRef)
 SOFT_LINK_POINTER_OPTIONAL(CoreMedia, kCMTextVerticalLayout_LeftToRight, CFStringRef)
 SOFT_LINK_POINTER_OPTIONAL(CoreMedia, kCMTextVerticalLayout_RightToLeft, CFStringRef)
+SOFT_LINK_POINTER_OPTIONAL(CoreMedia, kCMTextMarkupAttribute_BaseFontSizePercentageRelativeToVideoHeight, CFStringRef)
+SOFT_LINK_POINTER_OPTIONAL(CoreMedia, kCMTextMarkupAttribute_RelativeFontSize, CFStringRef)
+SOFT_LINK_POINTER_OPTIONAL(CoreMedia, kCMTextMarkupAttribute_FontFamilyName, CFStringRef)
 
 #define kCMTextMarkupAttribute_Alignment getkCMTextMarkupAttribute_Alignment()
 #define kCMTextMarkupAlignmentType_Start getkCMTextMarkupAlignmentType_Start()
@@ -66,6 +71,9 @@ SOFT_LINK_POINTER_OPTIONAL(CoreMedia, kCMTextVerticalLayout_RightToLeft, CFStrin
 #define kCMTextMarkupAttribute_VerticalLayout getkCMTextMarkupAttribute_VerticalLayout()
 #define kCMTextVerticalLayout_LeftToRight getkCMTextVerticalLayout_LeftToRight()
 #define kCMTextVerticalLayout_RightToLeft getkCMTextVerticalLayout_RightToLeft()
+#define kCMTextMarkupAttribute_BaseFontSizePercentageRelativeToVideoHeight getkCMTextMarkupAttribute_BaseFontSizePercentageRelativeToVideoHeight()
+#define kCMTextMarkupAttribute_RelativeFontSize getkCMTextMarkupAttribute_RelativeFontSize()
+#define kCMTextMarkupAttribute_FontFamilyName getkCMTextMarkupAttribute_FontFamilyName()
 
 using namespace std;
 
@@ -84,7 +92,7 @@ InbandTextTrackPrivateAVF::~InbandTextTrackPrivateAVF()
     disconnect();
 }
 
-void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attributedString, StringBuilder& content, StringBuilder& settings)
+void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attributedString, GenericCueData* cueData)
 {
     // Some of the attributes we translate into per-cue WebVTT settings are are repeated on each part of an attributed string so only
     // process the first instance of each.
@@ -93,10 +101,12 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
         Position = 1 << 1,
         Size = 1 << 2,
         Vertical = 1 << 3,
-        Align = 1 << 4
+        Align = 1 << 4,
+        FontName = 1 << 5
     };
     unsigned processed = 0;
 
+    StringBuilder content;
     String attributedStringValue = CFAttributedStringGetString(attributedString);
     CFIndex length = attributedStringValue.length();
     if (!length)
@@ -110,6 +120,7 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
             continue;
 
         StringBuilder tagStart;
+        CFStringRef valueString;
         String tagEnd;
         CFIndex attributeCount = CFDictionaryGetCount(attributes);
         Vector<const void*> keys(attributeCount);
@@ -123,7 +134,7 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
                 continue;
 
             if (CFStringCompare(key, kCMTextMarkupAttribute_Alignment, 0) == kCFCompareEqualTo) {
-                CFStringRef valueString = static_cast<CFStringRef>(value);
+                valueString = static_cast<CFStringRef>(value);
                 if (CFGetTypeID(valueString) != CFStringGetTypeID() || !CFStringGetLength(valueString))
                     continue;
                 if (processed & Align)
@@ -131,11 +142,11 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
                 processed |= Align;
 
                 if (CFStringCompare(valueString, kCMTextMarkupAlignmentType_Start, 0) == kCFCompareEqualTo)
-                    settings.append("align:start ");
+                    cueData->setAlign(GenericCueData::Start);
                 else if (CFStringCompare(valueString, kCMTextMarkupAlignmentType_Middle, 0) == kCFCompareEqualTo)
-                    settings.append("align:middle ");
+                    cueData->setAlign(GenericCueData::Middle);
                 else if (CFStringCompare(valueString, kCMTextMarkupAlignmentType_End, 0) == kCFCompareEqualTo)
-                    settings.append("align:end ");
+                    cueData->setAlign(GenericCueData::End);
                 else
                     ASSERT_NOT_REACHED();
 
@@ -170,9 +181,6 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
             }
 
             if (CFStringCompare(key, kCMTextMarkupAttribute_OrthogonalLinePositionPercentageRelativeToWritingDirection, 0) == kCFCompareEqualTo) {
-                // Ignore the line position if the attributes also specify "size" so we keep WebVTT's default line logic
-                if (CFDictionaryGetValue(attributes, kCMTextMarkupAttribute_WritingDirectionSizePercentage))
-                    continue;
                 if (CFGetTypeID(value) != CFNumberGetTypeID())
                     continue;
                 if (processed & Line)
@@ -180,9 +188,9 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
                 processed |= Line;
 
                 CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
-                double position;
-                CFNumberGetValue(valueNumber, kCFNumberFloat64Type, &position);
-                settings.append(String::format("line:%ld%% ", lrint(position)));
+                double line;
+                CFNumberGetValue(valueNumber, kCFNumberFloat64Type, &line);
+                cueData->setLine(line);
                 continue;
             }
 
@@ -196,7 +204,7 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
                 CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
                 double position;
                 CFNumberGetValue(valueNumber, kCFNumberFloat64Type, &position);
-                settings.append(String::format("position:%ld%% ", lrint(position)));
+                cueData->setPosition(position);
                 continue;
             }
 
@@ -208,16 +216,66 @@ void InbandTextTrackPrivateAVF::processCueAttributes(CFAttributedStringRef attri
                 processed |= Size;
 
                 CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
-                double position;
-                CFNumberGetValue(valueNumber, kCFNumberFloat64Type, &position);
-                settings.append(String::format("size:%ld%% ", lrint(position)));
+                double size;
+                CFNumberGetValue(valueNumber, kCFNumberFloat64Type, &size);
+                cueData->setSize(size);
+                continue;
+            }
+
+            if (CFStringCompare(key, kCMTextMarkupAttribute_VerticalLayout, 0) == kCFCompareEqualTo) {
+                valueString = static_cast<CFStringRef>(value);
+                if (CFGetTypeID(valueString) != CFStringGetTypeID() || !CFStringGetLength(valueString))
+                    continue;
+                
+                if (CFStringCompare(valueString, kCMTextVerticalLayout_LeftToRight, 0) == kCFCompareEqualTo)
+                    tagStart.append(leftToRightMark);
+                else if (CFStringCompare(valueString, kCMTextVerticalLayout_RightToLeft, 0) == kCFCompareEqualTo)
+                    tagStart.append(rightToLeftMark);
+                continue;
+            }
+            
+            if (CFStringCompare(key, kCMTextMarkupAttribute_BaseFontSizePercentageRelativeToVideoHeight, 0) == kCFCompareEqualTo) {
+                if (CFGetTypeID(value) != CFNumberGetTypeID())
+                    continue;
+                
+                CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
+                double baseFontSize;
+                CFNumberGetValue(valueNumber, kCFNumberFloat64Type, &baseFontSize);
+                cueData->setBaseFontSize(baseFontSize);
+                continue;
+            }
+            
+            if (CFStringCompare(key, kCMTextMarkupAttribute_RelativeFontSize, 0) == kCFCompareEqualTo) {
+                if (CFGetTypeID(value) != CFNumberGetTypeID())
+                    continue;
+                
+                CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
+                double relativeFontSize;
+                CFNumberGetValue(valueNumber, kCFNumberFloat64Type, &relativeFontSize);
+                cueData->setRelativeFontSize(relativeFontSize);
+                continue;
+            }
+
+            if (CFStringCompare(key, kCMTextMarkupAttribute_FontFamilyName, 0) == kCFCompareEqualTo) {
+                valueString = static_cast<CFStringRef>(value);
+                if (CFGetTypeID(valueString) != CFStringGetTypeID() || !CFStringGetLength(valueString))
+                    continue;
+                if (processed & FontName)
+                    continue;
+                processed |= FontName;
+                
+                cueData->setFontName(valueString);
                 continue;
             }
         }
+
         content.append(tagStart);
         content.append(attributedStringValue.substring(effectiveRange.location, effectiveRange.length));
         content.append(tagEnd);
     }
+
+    if (content.length())
+        cueData->setContent(content.toString());
 }
 
 void InbandTextTrackPrivateAVF::processCue(CFArrayRef attributedStrings, double time)
@@ -228,21 +286,46 @@ void InbandTextTrackPrivateAVF::processCue(CFArrayRef attributedStrings, double
     if (m_havePartialCue) {
         // Cues do not have an explicit duration, they are displayed until the next "cue" (which might be empty) is emitted.
         m_currentCueEndTime = time;
-        LOG(Media, "InbandTextTrackPrivateAVF::processCue flushing cue: start=%.2f, end=%.2f, settings=\"%s\", content=\"%s\" \n",
-            m_currentCueStartTime, m_currentCueEndTime,
-            m_currentCueSettings.toString().utf8().data(), m_currentCueContent.toString().utf8().data());
-        m_player->flushCurrentCue(this);
+
+        if (m_currentCueEndTime >= m_currentCueStartTime) {
+            for (size_t i = 0; i < m_cues.size(); i++) {
+
+                GenericCueData* cueData = m_cues[i].get();
+
+                LOG(Media, "InbandTextTrackPrivateAVF::processCue flushing cue: start=%.2f, end=%.2f, content=\"%s\" \n",
+                    m_currentCueStartTime, m_currentCueEndTime, cueData->content().utf8().data());
+                
+                if (!cueData->content().length())
+                    continue;
+                
+                cueData->setStartTime(m_currentCueStartTime);
+                cueData->setEndTime(m_currentCueEndTime);
+                
+                // AVFoundation cue "position" is to the center of the text so adjust relative to the edge because we will use it to
+                // set CSS "left".
+                if (cueData->position() >= 0 && cueData->size() > 0)
+                    cueData->setPosition(cueData->position() - cueData->size() / 2);
+                
+                m_player->addGenericCue(this, cueData);
+            }
+        } else
+            LOG(Media, "InbandTextTrackPrivateAVF::processCue negative length cue(s) ignored: start=%.2f, end=%.2f\n", m_currentCueStartTime, m_currentCueEndTime);
+
         resetCueValues();
     }
 
     CFIndex count = CFArrayGetCount(attributedStrings);
+    if (!count)
+        return;
+
     for (CFIndex i = 0; i < count; i++) {
         CFAttributedStringRef attributedString = static_cast<CFAttributedStringRef>(CFArrayGetValueAtIndex(attributedStrings, i));
 
         if (!attributedString || !CFAttributedStringGetLength(attributedString))
             continue;
 
-        processCueAttributes(attributedString, m_currentCueContent, m_currentCueSettings);
+        m_cues.append(adoptPtr(new GenericCueData));
+        processCueAttributes(attributedString, m_cues[i].get());
         m_currentCueStartTime = time;
         m_havePartialCue = true;
     }
@@ -256,17 +339,13 @@ void InbandTextTrackPrivateAVF::disconnect()
 
 void InbandTextTrackPrivateAVF::resetCueValues()
 {
-    if (m_havePartialCue && !m_currentCueEndTime) {
-        LOG(Media, "InbandTextTrackPrivateAVF::resetCueValues flushing data for cue: start=%.2f, end=%.2f, settings=\"%s\", content=\"%s\" \n",
-            m_currentCueStartTime, m_currentCueEndTime, m_currentCueSettings.toString().utf8().data(), m_currentCueContent.toString().utf8().data());
-    }
+    if (m_havePartialCue && !m_currentCueEndTime)
+        LOG(Media, "InbandTextTrackPrivateAVF::resetCueValues flushing data for cues: start=%.2f\n", m_currentCueStartTime);
 
+    m_cues.resize(0);
     m_havePartialCue = false;
-    m_currentCueId = String();
     m_currentCueStartTime = 0;
     m_currentCueEndTime = 0;
-    m_currentCueSettings.clear();
-    m_currentCueContent.clear();
 }
 
 void InbandTextTrackPrivateAVF::setMode(InbandTextTrackPrivate::Mode newMode)
index 53a2085..25623bc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 namespace WebCore {
 
 class MediaPlayerPrivateAVFoundation;
+class GenericCueData;
 
 class InbandTextTrackPrivateAVF : public InbandTextTrackPrivate {
 public:
-    ~InbandTextTrackPrivateAVF();
-
-    String id() const { return m_currentCueId; }
-    double start() const { return m_currentCueStartTime; }
-    double end() const { return m_currentCueEndTime; }
-    String settings() { return m_currentCueSettings.toString(); }
-    String content() { return m_currentCueContent.toString(); }
 
-    void processCue(CFArrayRef, double);
-
-    void resetCueValues();
+    ~InbandTextTrackPrivateAVF();
 
     virtual void setMode(InbandTextTrackPrivate::Mode) OVERRIDE;
 
@@ -60,16 +52,18 @@ public:
     bool hasBeenReported() const { return m_hasBeenReported; }
     void setHasBeenReported(bool reported) { m_hasBeenReported = reported; }
 
+    void processCue(CFArrayRef, double);
+    void resetCueValues();
+
 protected:
     InbandTextTrackPrivateAVF(MediaPlayerPrivateAVFoundation*);
 
-    void processCueAttributes(CFAttributedStringRef, StringBuilder& content, StringBuilder& settings);
+    void processCueAttributes(CFAttributedStringRef, GenericCueData*);
 
-    String m_currentCueId;
     double m_currentCueStartTime;
     double m_currentCueEndTime;
-    StringBuilder m_currentCueSettings;
-    StringBuilder m_currentCueContent;
+
+    Vector<OwnPtr<GenericCueData> > m_cues;
 
     MediaPlayerPrivateAVFoundation* m_player;
     int m_index;
index 8654ea1..4d64ba1 100644 (file)
@@ -582,6 +582,11 @@ void MediaPlayerPrivateAVFoundation::seekCompleted(bool finished)
     LOG(Media, "MediaPlayerPrivateAVFoundation::seekCompleted(%p) - finished = %d", this, finished);
     UNUSED_PARAM(finished);
 
+#if HAVE(AVFOUNDATION_TEXT_TRACK_SUPPORT)
+    if (currentTrack())
+        currentTrack()->resetCueValues();
+#endif
+
     m_seekTo = MediaPlayer::invalidTime();
     updateStates();
     m_player->timeChanged();
@@ -811,19 +816,13 @@ void MediaPlayerPrivateAVFoundation::dispatchNotification()
 }
 
 #if HAVE(AVFOUNDATION_TEXT_TRACK_SUPPORT)
-void MediaPlayerPrivateAVFoundation::flushCurrentCue(InbandTextTrackPrivateAVF* track)
+void MediaPlayerPrivateAVFoundation::addGenericCue(InbandTextTrackPrivateAVF* track, GenericCueData* cueData)
 {
     if (!track->client())
         return;
 
-    // AVFoundation returns a cue every time the data is buffered, only add it once.
-    if (track->client()->hasCue(track, track->start(), track->end(), track->id(), track->content(), track->settings())) {
-        LOG(Media, "MediaPlayerPrivateAVFoundation::flushCurrentCue(%p) - already have cue for time %.2f", this, track->start());
-        return;
-    }
-
-    LOG(Media, "MediaPlayerPrivateAVFoundation::flushCurrentCue(%p) - adding cue for time %.2f", this, track->start());
-    track->client()->addCue(track, track->start(), track->end(), track->id(), track->content(), track->settings());
+    LOG(Media, "MediaPlayerPrivateAVFoundation::addGenericCue(%p) - adding cue for time %.2f", this, cueData->startTime());
+    track->client()->addGenericCue(track, cueData);
 }
 
 void MediaPlayerPrivateAVFoundation::configureInbandTracks()
index a6cdccc..987b7d5 100644 (file)
@@ -36,6 +36,7 @@
 namespace WebCore {
 
 class InbandTextTrackPrivateAVF;
+class GenericCueData;
 
 class MediaPlayerPrivateAVFoundation : public MediaPlayerPrivateInterface {
 public:
@@ -118,7 +119,7 @@ public:
     void clearMainThreadPendingFlag();
 
 #if HAVE(AVFOUNDATION_TEXT_TRACK_SUPPORT)
-    void flushCurrentCue(InbandTextTrackPrivateAVF*);
+    void addGenericCue(InbandTextTrackPrivateAVF*, GenericCueData*);
     void trackModeChanged();
 #endif
 
index a03e915..ea9d488 100644 (file)
@@ -106,6 +106,7 @@ SOFT_LINK_CLASS(AVFoundation, AVMediaSelectionOption)
 SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicLegible, NSString *)
 SOFT_LINK_POINTER(AVFoundation, AVMediaTypeSubtitle, NSString *)
 SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicContainsOnlyForcedSubtitles, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVPlayerItemLegibleOutputTextStylingResolutionSourceAndRulesOnly, NSString *)
 
 #define AVPlayerItemLegibleOutput getAVPlayerItemLegibleOutputClass()
 #define AVMediaSelectionGroup getAVMediaSelectionGroupClass()
@@ -113,6 +114,7 @@ SOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicContainsOnlyForcedSubtitles
 #define AVMediaCharacteristicLegible getAVMediaCharacteristicLegible()
 #define AVMediaTypeSubtitle getAVMediaTypeSubtitle()
 #define AVMediaCharacteristicContainsOnlyForcedSubtitles getAVMediaCharacteristicContainsOnlyForcedSubtitles()
+#define AVPlayerItemLegibleOutputTextStylingResolutionSourceAndRulesOnly getAVPlayerItemLegibleOutputTextStylingResolutionSourceAndRulesOnly()
 #endif
 
 #define kCMTimeZero getkCMTimeZero()
@@ -391,7 +393,6 @@ void MediaPlayerPrivateAVFoundationObjC::createAVPlayer()
 #if HAVE(AVFOUNDATION_TEXT_TRACK_SUPPORT)
     [m_avPlayer.get() setAppliesMediaSelectionCriteriaAutomatically:YES];
 #endif
-    
 
     if (m_avPlayerItem)
         [m_avPlayer.get() replaceCurrentItemWithPlayerItem:m_avPlayerItem.get()];
@@ -410,7 +411,7 @@ void MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem()
 
     // Create the player item so we can load media data. 
     m_avPlayerItem.adoptNS([[AVPlayerItem alloc] initWithAsset:m_avAsset.get()]);
-    
+
     [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(didEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:m_avPlayerItem.get()];
 
     for (NSString *keyName in itemKVOProperties())
@@ -897,6 +898,7 @@ void MediaPlayerPrivateAVFoundationObjC::tracksChanged()
 
         [m_legibleOutput.get() setDelegate:m_objcObserver.get() queue:dispatch_get_main_queue()];
         [m_legibleOutput.get() setAdvanceIntervalForDelegateInvocation:NSTimeIntervalSince1970];
+        [m_legibleOutput.get() setTextStylingResolution:AVPlayerItemLegibleOutputTextStylingResolutionSourceAndRulesOnly];
         [m_avPlayerItem.get() addOutput:m_legibleOutput.get()];
     }
 #endif
@@ -1212,7 +1214,7 @@ void MediaPlayerPrivateAVFoundationObjC::processTextTracks()
         LOG(Media, "MediaPlayerPrivateAVFoundationObjC::processTextTracks(%p) - nil mediaSelectionGroup", this);
         return;
     }
-
+    
     Vector<RefPtr<InbandTextTrackPrivateAVF> > removedTextTracks = m_textTracks;
     NSArray *legibleOptions = [AVMediaSelectionGroup playableMediaSelectionOptionsFromArray:[legibleGroup options]];
     for (AVMediaSelectionOptionType *option in legibleOptions) {
@@ -1228,13 +1230,8 @@ void MediaPlayerPrivateAVFoundationObjC::processTextTracks()
         if (!newTrack)
             continue;
 
-        if ([[option mediaType] isEqualToString:AVMediaTypeSubtitle]) {
-            if (![option hasMediaCharacteristic:AVMediaCharacteristicContainsOnlyForcedSubtitles]) {
-                AVMediaSelectionOptionType *forcedOnlyOption = [option associatedMediaSelectionOptionInMediaSelectionGroup:legibleGroup];
-                if (forcedOnlyOption)
-                    continue;
-            }
-        }
+        if ([[option mediaType] isEqualToString:AVMediaTypeSubtitle] && [option hasMediaCharacteristic:AVMediaCharacteristicContainsOnlyForcedSubtitles])
+            continue;
 
         m_textTracks.append(InbandTextTrackPrivateAVFObjC::create(this, option));
     }
@@ -1275,6 +1272,9 @@ void MediaPlayerPrivateAVFoundationObjC::processCue(NSArray *attributedStrings,
 void MediaPlayerPrivateAVFoundationObjC::setCurrentTrack(InbandTextTrackPrivateAVF *track)
 {
     InbandTextTrackPrivateAVFObjC* trackPrivate = static_cast<InbandTextTrackPrivateAVFObjC*>(track);
+    if (m_currentTrack == trackPrivate)
+        return;
+
     AVMediaSelectionOptionType *mediaSelectionOption = trackPrivate ? trackPrivate->mediaSelectionOption() : 0;
 
     LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setCurrentTrack(%p) - selecting media option %p", this, mediaSelectionOption);
@@ -1424,6 +1424,8 @@ NSArray* itemKVOProperties()
         return;
 
     dispatch_async(dispatch_get_main_queue(), ^{
+        if (!m_callback)
+            return;
         m_callback->processCue(strings, CMTimeGetSeconds(itemTime));
     });
 }