Title: [94011] trunk/Source/WebCore
Revision
94011
Author
[email protected]
Date
2011-08-29 13:47:06 -0700 (Mon, 29 Aug 2011)

Log Message

Implement WebVTT Cue Text Parsing rules and DOM construction
https://bugs.webkit.org/show_bug.cgi?id=64132

Patch by Anna Cavender <[email protected]> on 2011-08-29
Reviewed by Adam Barth.

Tests in media/track, particularly track-webvtt-tc[022 - 028]*.

* CMakeLists.txt:
* GNUmakefile.list.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.xcodeproj/project.pbxproj:
* html/TextTrackCue.cpp:
* html/TextTrackCue.h:
* platform/track/CueParser.cpp:
* platform/track/CueParser.h:
* platform/track/WebVTTParser.cpp:
* platform/track/WebVTTParser.h:
* platform/track/WebVTTToken.h: Added.
* platform/track/WebVTTTokenizer.cpp: Added.
* platform/track/WebVTTTokenizer.h: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/CMakeLists.txt (94010 => 94011)


--- trunk/Source/WebCore/CMakeLists.txt	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/CMakeLists.txt	2011-08-29 20:47:06 UTC (rev 94011)
@@ -2039,6 +2039,7 @@
         loader/CueLoader.cpp
         platform/track/CueParser.cpp
         platform/track/WebVTTParser.cpp
+        platform/track/WebVTTTokenizer.cpp
     )
 ENDIF()
 

Modified: trunk/Source/WebCore/ChangeLog (94010 => 94011)


--- trunk/Source/WebCore/ChangeLog	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/ChangeLog	2011-08-29 20:47:06 UTC (rev 94011)
@@ -1,3 +1,27 @@
+2011-08-29  Anna Cavender  <[email protected]>
+
+        Implement WebVTT Cue Text Parsing rules and DOM construction
+        https://bugs.webkit.org/show_bug.cgi?id=64132
+
+        Reviewed by Adam Barth.
+
+        Tests in media/track, particularly track-webvtt-tc[022 - 028]*.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.xcodeproj/project.pbxproj:
+        * html/TextTrackCue.cpp:
+        * html/TextTrackCue.h:
+        * platform/track/CueParser.cpp:
+        * platform/track/CueParser.h:
+        * platform/track/WebVTTParser.cpp:
+        * platform/track/WebVTTParser.h:
+        * platform/track/WebVTTToken.h: Added.
+        * platform/track/WebVTTTokenizer.cpp: Added.
+        * platform/track/WebVTTTokenizer.h: Added.
+
 2011-08-29  Patrick Gansterer  <[email protected]>
 
         Add parsing support for extended attributes on IDL constants

Modified: trunk/Source/WebCore/GNUmakefile.list.am (94010 => 94011)


--- trunk/Source/WebCore/GNUmakefile.list.am	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2011-08-29 20:47:06 UTC (rev 94011)
@@ -2875,6 +2875,9 @@
 	Source/WebCore/platform/track/CueParserPrivate.h \
 	Source/WebCore/platform/track/WebVTTParser.cpp \
 	Source/WebCore/platform/track/WebVTTParser.h \
+	Source/WebCore/platform/track/WebVTTToken.h \
+	Source/WebCore/platform/track/WebVTTTokenizer.h \
+	Source/WebCore/platform/track/WebVTTTokenizer.cpp \
 	Source/WebCore/platform/TreeShared.h \
 	Source/WebCore/platform/URLString.h \
 	Source/WebCore/platform/UUID.cpp \

Modified: trunk/Source/WebCore/WebCore.gypi (94010 => 94011)


--- trunk/Source/WebCore/WebCore.gypi	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/WebCore.gypi	2011-08-29 20:47:06 UTC (rev 94011)
@@ -4394,6 +4394,9 @@
             'platform/track/CueParserPrivate.h',
             'platform/track/WebVTTParser.cpp',
             'platform/track/WebVTTParser.h',
+            'platform/track/WebVTTToken.h',
+            'platform/track/WebVTTTokenizer.cpp',
+            'platform/track/WebVTTTokenizer.h',
             'platform/win/BString.cpp',
             'platform/win/BString.h',
             'platform/win/BitmapInfo.cpp',

Modified: trunk/Source/WebCore/WebCore.pro (94010 => 94011)


--- trunk/Source/WebCore/WebCore.pro	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/WebCore.pro	2011-08-29 20:47:06 UTC (rev 94011)
@@ -2121,6 +2121,8 @@
     platform/track/CueParser.h \
     platform/track/CueParserPrivate.h \
     platform/track/WebVTTParser.h \
+    platform/track/WebVTTToken.h \
+    platform/track/WebVTTTokenizer.h \
     platform/Widget.h \
     platform/PlatformStrategies.h \
     platform/LocalizedStrings.h \

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (94010 => 94011)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2011-08-29 20:47:06 UTC (rev 94011)
@@ -4090,6 +4090,9 @@
 		ABDDFE790A5C6E7000A3E11D /* RenderMenuList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABDDFE730A5C6E6F00A3E11D /* RenderMenuList.cpp */; };
 		ABDDFE7A0A5C6E7000A3E11D /* RenderMenuList.h in Headers */ = {isa = PBXBuildFile; fileRef = ABDDFE740A5C6E7000A3E11D /* RenderMenuList.h */; };
 		ADDF1AD71257CD9A0003A759 /* RenderSVGPath.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDF1AD51257CD9A0003A759 /* RenderSVGPath.h */; };
+		B10B6980140C174000BC1C26 /* WebVTTToken.h in Headers */ = {isa = PBXBuildFile; fileRef = B10B697D140C174000BC1C26 /* WebVTTToken.h */; };
+		B10B6981140C174000BC1C26 /* WebVTTTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B10B697E140C174000BC1C26 /* WebVTTTokenizer.cpp */; };
+		B10B6982140C174000BC1C26 /* WebVTTTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = B10B697F140C174000BC1C26 /* WebVTTTokenizer.h */; };
 		B14353D5138EA8ED00D53276 /* MediaStreamList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B14353D1138EA8ED00D53276 /* MediaStreamList.cpp */; };
 		B14353D6138EA8ED00D53276 /* MediaStreamList.h in Headers */ = {isa = PBXBuildFile; fileRef = B14353D2138EA8ED00D53276 /* MediaStreamList.h */; };
 		B14353F8138EA95B00D53276 /* JSMediaStreamList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B14353F6138EA95B00D53276 /* JSMediaStreamList.cpp */; };
@@ -10632,6 +10635,9 @@
 		ABDDFE740A5C6E7000A3E11D /* RenderMenuList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderMenuList.h; sourceTree = "<group>"; };
 		ADDF1AD41257CD9A0003A759 /* RenderSVGPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGPath.cpp; sourceTree = "<group>"; };
 		ADDF1AD51257CD9A0003A759 /* RenderSVGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGPath.h; sourceTree = "<group>"; };
+		B10B697D140C174000BC1C26 /* WebVTTToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebVTTToken.h; path = platform/track/WebVTTToken.h; sourceTree = "<group>"; };
+		B10B697E140C174000BC1C26 /* WebVTTTokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebVTTTokenizer.cpp; path = platform/track/WebVTTTokenizer.cpp; sourceTree = "<group>"; };
+		B10B697F140C174000BC1C26 /* WebVTTTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebVTTTokenizer.h; path = platform/track/WebVTTTokenizer.h; sourceTree = "<group>"; };
 		B14353D1138EA8ED00D53276 /* MediaStreamList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaStreamList.cpp; sourceTree = "<group>"; };
 		B14353D2138EA8ED00D53276 /* MediaStreamList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamList.h; sourceTree = "<group>"; };
 		B14353D3138EA8ED00D53276 /* MediaStreamList.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaStreamList.idl; sourceTree = "<group>"; };
@@ -12975,6 +12981,9 @@
 			children = (
 				65C97AF208EA908800ACD273 /* config.h */,
 				EDEC98020AED7E170059137F /* WebCorePrefix.h */,
+				B10B697D140C174000BC1C26 /* WebVTTToken.h */,
+				B10B697E140C174000BC1C26 /* WebVTTTokenizer.cpp */,
+				B10B697F140C174000BC1C26 /* WebVTTTokenizer.h */,
 				9307061309E0CA8200B17FE4 /* DerivedSources.make */,
 				93F19B1908245E59001E9ABC /* Info.plist */,
 				29A812040FBB9B4100510293 /* accessibility */,
@@ -23439,6 +23448,8 @@
 				93500F3213FDE3BE0099EC24 /* NSScrollerImpDetails.h in Headers */,
 				D0A3A7311405A39800FB8ED3 /* ResourceLoaderOptions.h in Headers */,
 				BCE43897140B0051005E437E /* EventConstructors.h in Headers */,
+				B10B6980140C174000BC1C26 /* WebVTTToken.h in Headers */,
+				B10B6982140C174000BC1C26 /* WebVTTTokenizer.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -26248,6 +26259,7 @@
 				1A1414B513A0F0500019996C /* WebKitFontFamilyNames.cpp in Sources */,
 				DF9AFD7313FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.mm in Sources */,
 				BCE4389A140B0073005E437E /* JSEventConstructors.cpp in Sources */,
+				B10B6981140C174000BC1C26 /* WebVTTTokenizer.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/WebCore/html/TextTrackCue.cpp (94010 => 94011)


--- trunk/Source/WebCore/html/TextTrackCue.cpp	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/html/TextTrackCue.cpp	2011-08-29 20:47:06 UTC (rev 94011)
@@ -41,8 +41,9 @@
 
 namespace WebCore {
 
-TextTrackCue::TextTrackCue(const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit)
-    : m_id(id)
+TextTrackCue::TextTrackCue(ScriptExecutionContext* context, const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit)
+    : ActiveDOMObject(context, this)
+    , m_id(id)
     , m_startTime(start)
     , m_endTime(end)
     , m_content(content)
@@ -127,10 +128,14 @@
 
 PassRefPtr<DocumentFragment> TextTrackCue::getCueAsHTML()
 {
-    // FIXME(62883): Implement.
-    return DocumentFragment::create(0);
+    return m_documentFragment;
 }
 
+void TextTrackCue::setCueHTML(PassRefPtr<DocumentFragment> fragment)
+{
+    m_documentFragment = fragment;
+}
+
 bool TextTrackCue::isActive()
 {
     // FIXME(62885): Implement.
@@ -142,12 +147,21 @@
     m_isActive = active;
 }
 
+ScriptExecutionContext* TextTrackCue::scriptExecutionContext() const
+{
+    return ActiveDOMObject::scriptExecutionContext();
+}
+
 void TextTrackCue::parseSettings(const String& input)
 {
     // 4.8.10.13.3 Parse the WebVTT settings.
     // 1 - Initial setup.
     unsigned position = 0;
     while (position < input.length()) {
+        // Discard any space characters between or after settings (not in the spec, but we think it should be).
+        while (position < input.length() && WebVTTParser::isASpace(input[position]))
+            position++;
+
         // 2-4 Settings - get the next character representing a settings.
         char setting = input[position++];
         if (position >= input.length())
@@ -285,9 +299,6 @@
             break;
         }
 
-        // Discard any remaining space characters between or after settings (not in the spec, but we think it should be).
-        while (position < input.length() && WebVTTParser::isASpace(input[position]))
-            position++;
         continue;
 
 Otherwise:

Modified: trunk/Source/WebCore/html/TextTrackCue.h (94010 => 94011)


--- trunk/Source/WebCore/html/TextTrackCue.h	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/html/TextTrackCue.h	2011-08-29 20:47:06 UTC (rev 94011)
@@ -33,6 +33,7 @@
 
 #if ENABLE(VIDEO_TRACK)
 
+#include "ActiveDOMObject.h"
 #include "TextTrack.h"
 #include <wtf/PassOwnPtr.h>
 #include <wtf/RefCounted.h>
@@ -40,13 +41,14 @@
 namespace WebCore {
 
 class DocumentFragment;
+class ScriptExecutionContext;
 class TextTrack;
 
-class TextTrackCue : public RefCounted<TextTrackCue> {
+class TextTrackCue : public RefCounted<TextTrackCue>, public ActiveDOMObject {
 public:
-    static PassRefPtr<TextTrackCue> create(const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit)
+    static PassRefPtr<TextTrackCue> create(ScriptExecutionContext* context, const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit)
     {
-        return adoptRef(new TextTrackCue(id, start, end, content, settings, pauseOnExit));
+        return adoptRef(new TextTrackCue(context, id, start, end, content, settings, pauseOnExit));
     }
     
     enum Direction { Horizontal, VerticalGrowingLeft, VerticalGrowingRight };
@@ -71,12 +73,15 @@
 
     String getCueAsSource();
     PassRefPtr<DocumentFragment> getCueAsHTML();
+    void setCueHTML(PassRefPtr<DocumentFragment>);
 
     bool isActive();
     void setIsActive(bool);
+    
+    virtual ScriptExecutionContext* scriptExecutionContext() const;
 
 private:
-    TextTrackCue(const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit);
+    TextTrackCue(ScriptExecutionContext*, const String& id, double start, double end, const String& content, const String& settings, bool pauseOnExit);
 
     void parseSettings(const String&);
     
@@ -93,6 +98,7 @@
     int m_textPosition;
     int m_cueSize;
     Alignment m_cueAlignment;
+    RefPtr<DocumentFragment> m_documentFragment;
 
     bool m_isActive;
 };

Modified: trunk/Source/WebCore/platform/track/CueParser.cpp (94010 => 94011)


--- trunk/Source/WebCore/platform/track/CueParser.cpp	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/platform/track/CueParser.cpp	2011-08-29 20:47:06 UTC (rev 94011)
@@ -61,6 +61,7 @@
     options.crossOriginRequestPolicy = AllowCrossOriginRequests;
 
     m_client = client;
+    m_scriptExecutionContext = context;
 
     m_loader = ThreadableLoader::create(context, this, request, options);
 }
@@ -110,7 +111,7 @@
 void CueParser::createWebVTTParser()
 {
     if (!m_private) {
-        m_private = WebVTTParser::create(this);
+        m_private = WebVTTParser::create(this, m_scriptExecutionContext);
         m_client->trackLoadStarted();
     }
 }

Modified: trunk/Source/WebCore/platform/track/CueParser.h (94010 => 94011)


--- trunk/Source/WebCore/platform/track/CueParser.h	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/platform/track/CueParser.h	2011-08-29 20:47:06 UTC (rev 94011)
@@ -69,6 +69,9 @@
     void fetchParsedCues(Vector<RefPtr<TextTrackCue> >&);
     void newCuesParsed();
 
+protected:
+    ScriptExecutionContext* m_scriptExecutionContext;
+
 private:
     void createWebVTTParser();
  

Modified: trunk/Source/WebCore/platform/track/WebVTTParser.cpp (94010 => 94011)


--- trunk/Source/WebCore/platform/track/WebVTTParser.cpp	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/platform/track/WebVTTParser.cpp	2011-08-29 20:47:06 UTC (rev 94011)
@@ -34,6 +34,10 @@
 
 #include "WebVTTParser.h"
 
+#include "HTMLElement.h"
+#include "ProcessingInstruction.h"
+#include "SegmentedString.h"
+#include "Text.h"
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
@@ -78,8 +82,10 @@
     return string.toString();
 }
 
-WebVTTParser::WebVTTParser(CueParserPrivateClient* client)
-    : m_state(Initial)
+WebVTTParser::WebVTTParser(CueParserPrivateClient* client, ScriptExecutionContext* context)
+    : m_scriptExecutionContext(context)
+    , m_state(Initial)
+    , m_tokenizer(WebVTTTokenizer::create())
 {
     m_client = client;
 }
@@ -204,10 +210,26 @@
 
 void WebVTTParser::processCueText()
 {
-    // 51 - Cue text processing based on WebVTT cue text parsing rules and WebVTT cue text DOM construction rules.
-    // FIXME(64132): Process the cue text as per the cue text parsing rules. 
-    //     Source: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#webvtt-cue-text-parsing-rules
-    RefPtr<TextTrackCue> cue = TextTrackCue::create(m_currentId, m_currentStartTime, m_currentEndTime, m_currentContent.toString(), m_currentSettings, false);
+    // 51 - Cue text processing based on
+    // 4.8.10.13.4 WebVTT cue text parsing rules and
+    // 4.8.10.13.5 WebVTT cue text DOM construction rules.
+    if (m_currentContent.length() <= 0)
+        return;
+
+    ASSERT(m_scriptExecutionContext->isDocument());
+    Document* document = static_cast<Document*>(m_scriptExecutionContext);
+
+    m_attachmentRoot = DocumentFragment::create(document);
+    m_currentNode = m_attachmentRoot;
+    m_tokenizer->reset();
+    m_token.clear();
+
+    SegmentedString content(m_currentContent.toString());
+    while (m_tokenizer->nextToken(content, m_token))
+        constructTreeFromToken(document);
+    
+    RefPtr<TextTrackCue> cue = TextTrackCue::create(m_scriptExecutionContext, m_currentId, m_currentStartTime, m_currentEndTime, m_currentContent.toString(), m_currentSettings, false);
+    cue->setCueHTML(m_attachmentRoot);
     m_cuelist.append(cue);
     m_client->newCuesParsed();
 }
@@ -281,6 +303,60 @@
     return (value1 * secondsPerHour) + (value2 * secondsPerMinute) + value3 + ((double)value4 / 1000);
 }
 
+void WebVTTParser::constructTreeFromToken(Document* document)
+{
+    AtomicString tokenTagName(m_token.name().data(), m_token.name().size());
+    QualifiedName tagName(nullAtom, tokenTagName, xhtmlNamespaceURI);
+
+    switch (m_token.type()) {
+    case WebVTTTokenTypes::Character: {
+        String content(m_token.characters().data(), m_token.characters().size());
+        RefPtr<Text> child = Text::create(document, content);
+        m_currentNode->parserAddChild(child);
+        break;
+    }
+    case WebVTTTokenTypes::StartTag: {
+        RefPtr<HTMLElement> child;
+        if (isRecognizedTag(tokenTagName))
+            child = HTMLElement::create(tagName, document);
+        else if (m_token.name().size() == 1 && m_token.name()[0] == 'c')
+            child = HTMLElement::create(spanTag, document);
+        else if (m_token.name().size() == 1 && m_token.name()[0] == 'v')
+            child = HTMLElement::create(qTag, document);
+
+        if (child) {
+            if (m_token.classes().size() > 0) {
+                RefPtr<NamedNodeMap> attributeMap = NamedNodeMap::create();
+                attributeMap->addAttribute(Attribute::createMapped(classAttr, AtomicString(m_token.classes().data(), m_token.classes().size())));
+                child->setAttributeMap(attributeMap.release());
+            }
+            if (child->hasTagName(qTag))
+                child->setAttribute(titleAttr, String(m_token.annotation().data(), m_token.annotation().size()));
+            m_currentNode->parserAddChild(child);
+            m_currentNode = child;
+        }
+        break;
+    }
+    case WebVTTTokenTypes::EndTag:
+        if (isRecognizedTag(tokenTagName)
+            || m_token.name().size() == 1 && m_token.name()[0] == 'c'
+            || m_token.name().size() == 1 && m_token.name()[0] == 'v')
+            if (m_currentNode->parentNode())
+                m_currentNode = m_currentNode->parentNode();
+        break;
+    case WebVTTTokenTypes::TimestampTag: {
+        unsigned position = 0;
+        double time = collectTimeStamp(m_token.characters().data(), &position);
+        if (time != malformedTime)
+            m_currentNode->parserAddChild(ProcessingInstruction::create(document, "timestamp", String(m_token.characters().data(), m_token.characters().size())));
+        break;
+    }
+    default:
+        break;
+    }
+    m_token.clear();
+}
+
 void WebVTTParser::skipWhiteSpace(const String& line, unsigned* position)
 {
     while (*position < line.length() && isASpace(line[*position]))

Modified: trunk/Source/WebCore/platform/track/WebVTTParser.h (94010 => 94011)


--- trunk/Source/WebCore/platform/track/WebVTTParser.h	2011-08-29 20:32:32 UTC (rev 94010)
+++ trunk/Source/WebCore/platform/track/WebVTTParser.h	2011-08-29 20:47:06 UTC (rev 94011)
@@ -34,11 +34,17 @@
 #if ENABLE(VIDEO_TRACK)
 
 #include "CueParserPrivate.h"
+#include "Document.h"
+#include "DocumentFragment.h"
+#include "HTMLNames.h"
+#include "WebVTTTokenizer.h"
 #include <wtf/PassOwnPtr.h>
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
+using namespace HTMLNames;
+
 static const int secondsPerHour = 3600;
 static const int secondsPerMinute = 60;
 static const double malformedTime = -1;
@@ -49,13 +55,22 @@
     
     enum ParseState { Initial, Header, Id, TimingsAndSettings, CueText, BadCue };
 
-    static PassOwnPtr<WebVTTParser> create(CueParserPrivateClient* client)
+    static PassOwnPtr<WebVTTParser> create(CueParserPrivateClient* client, ScriptExecutionContext* context)
     {
-        return adoptPtr(new WebVTTParser(client));
+        return adoptPtr(new WebVTTParser(client, context));
     }
     
     static bool hasRequiredFileIdentifier(const char* data, unsigned length);
 
+    static inline bool isRecognizedTag(const AtomicString& tagName)
+    {
+        return tagName == iTag
+            || tagName == bTag
+            || tagName == uTag
+            || tagName == rubyTag
+            || tagName == rtTag;
+    }
+
     static inline bool isASpace(char c)
     {
         // WebVTT space characters are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), U+000A LINE FEED (LF), U+000C FORM FEED (FF), and U+000D CARRIAGE RETURN    (CR).
@@ -69,8 +84,9 @@
     virtual void parseBytes(const char* data, unsigned length);
 
 protected:
-    WebVTTParser(CueParserPrivateClient*);
+    WebVTTParser(CueParserPrivateClient*, ScriptExecutionContext*);
     
+    ScriptExecutionContext* m_scriptExecutionContext;
     ParseState m_state;
 
 private:
@@ -85,13 +101,21 @@
     void skipWhiteSpace(const String&, unsigned*);
     static void skipLineTerminator(const char* data, unsigned length, unsigned*);
     static String collectNextLine(const char* data, unsigned length, unsigned*);
+    
+    void constructTreeFromToken(Document*);
 
     String m_currentId;
     double m_currentStartTime;
     double m_currentEndTime;
     StringBuilder m_currentContent;
     String m_currentSettings;
+    
+    WebVTTToken m_token;
+    OwnPtr<WebVTTTokenizer> m_tokenizer;
 
+    RefPtr<DocumentFragment> m_attachmentRoot;
+    RefPtr<ContainerNode> m_currentNode;
+
     CueParserPrivateClient* m_client;
 
     Vector<RefPtr<TextTrackCue> > m_cuelist;

Added: trunk/Source/WebCore/platform/track/WebVTTToken.h (0 => 94011)


--- trunk/Source/WebCore/platform/track/WebVTTToken.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/track/WebVTTToken.h	2011-08-29 20:47:06 UTC (rev 94011)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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 WebVTTToken_h
+#define WebVTTToken_h
+
+#if ENABLE(VIDEO_TRACK)
+
+#include "MarkupTokenBase.h"
+
+namespace WebCore {
+
+class WebVTTTokenTypes {
+public:
+    enum Type {
+        Uninitialized,
+        Character,
+        StartTag,
+        EndTag,
+        TimestampTag,
+        EndOfFile,
+    };
+};
+
+class WebVTTToken : public MarkupTokenBase<WebVTTTokenTypes> {
+public:
+    void appendToName(UChar character)
+    {
+        ASSERT(m_type == WebVTTTokenTypes::StartTag || m_type == WebVTTTokenTypes::EndTag);
+        MarkupTokenBase<WebVTTTokenTypes>::appendToName(character);
+    }
+    
+    const DataVector& name() const
+    {
+        return MarkupTokenBase<WebVTTTokenTypes>::name();
+    }
+    
+    const DataVector& characters() const
+    {
+        ASSERT(m_type == Type::Character || m_type == Type::TimestampTag);
+        return m_data;
+    }
+    
+    void beginEmptyStartTag()
+    {
+        ASSERT(m_type == Type::Uninitialized);
+        m_type = Type::StartTag;
+        m_currentAttribute = 0;
+        m_attributes.clear();
+        m_data.clear();
+    }
+ 
+    void beginTimestampTag(UChar character)
+    {
+        ASSERT(character);
+        ASSERT(m_type == Type::Uninitialized);
+        m_type = Type::TimestampTag;
+        m_selfClosing = true;
+        m_data.append(character);
+    }
+    
+    void appendToTimestamp(UChar character)
+    {
+        ASSERT(character);
+        ASSERT(m_type == Type::TimestampTag);
+        m_data.append(character);
+    }
+
+    void appendToClass(UChar character)
+    {
+        appendToStartType(character);
+    }
+
+    void addNewClass()
+    {
+        ASSERT(m_type == Type::StartTag);
+        if (!m_classes.isEmpty())
+            m_classes.append(' ');
+        m_classes.append(m_currentBuffer);
+        m_currentBuffer.clear();
+    }
+    
+    const DataVector& classes() const
+    {
+        return m_classes;
+    }
+
+    void appendToAnnotation(UChar character)
+    {
+        appendToStartType(character);
+    }
+        
+    void addNewAnnotation()
+    {
+        ASSERT(m_type == Type::StartTag);
+        m_annotation.clear();
+        m_annotation.append(m_currentBuffer);
+        m_currentBuffer.clear();
+    }
+    
+    const DataVector& annotation() const
+    {
+        return m_annotation;
+    }
+    
+    void clear()
+    {
+        m_annotation.clear();
+        m_classes.clear();
+        m_currentBuffer.clear();
+        MarkupTokenBase<WebVTTTokenTypes>::clear();
+    }
+
+private:
+    void appendToStartType(UChar character)
+    {
+        ASSERT(character);
+        ASSERT(m_type == Type::StartTag);
+        m_currentBuffer.append(character);
+    }
+
+    DataVector m_annotation;
+    DataVector m_classes;
+    DataVector m_currentBuffer;
+};
+
+}
+
+#endif
+#endif

Added: trunk/Source/WebCore/platform/track/WebVTTTokenizer.cpp (0 => 94011)


--- trunk/Source/WebCore/platform/track/WebVTTTokenizer.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/track/WebVTTTokenizer.cpp	2011-08-29 20:47:06 UTC (rev 94011)
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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 "WebVTTTokenizer.h"
+
+#include "MarkupTokenizerInlineMethods.h"
+
+namespace WebCore {
+
+#define WEBVTT_BEGIN_STATE(stateName) BEGIN_STATE(WebVTTTokenizerState, stateName)
+#define WEBVTT_ADVANCE_TO(stateName) ADVANCE_TO(WebVTTTokenizerState, stateName)
+
+WebVTTTokenizer::WebVTTTokenizer()
+{
+    reset();
+}
+
+template<>
+inline bool MarkupTokenizerBase<WebVTTToken, WebVTTTokenizerState>::shouldSkipNullCharacters() const
+{
+    return true;
+}
+
+inline bool vectorEqualsString(const Vector<UChar, 32>& vector, const String& string)
+{
+    if (vector.size() != string.length())
+        return false;
+    const UChar* stringData = string.characters();
+    const UChar* vectorData = vector.data();
+    return !memcmp(stringData, vectorData, vector.size() * sizeof(UChar));
+}
+
+void WebVTTTokenizer::reset()
+{
+    m_state = WebVTTTokenizerState::DataState;
+    m_token = 0;
+    m_lineNumber = 0;
+    m_buffer.clear();
+}
+    
+bool WebVTTTokenizer::nextToken(SegmentedString& source, WebVTTToken& token)
+{
+    // If we have a token in progress, then we're supposed to be called back
+    // with the same token so we can finish it.
+    ASSERT(!m_token || m_token == &token || token.type() == WebVTTTokenTypes::Uninitialized);
+    m_token = &token;
+
+    if (source.isEmpty() || !m_inputStreamPreprocessor.peek(source, m_lineNumber))
+        return haveBufferedCharacterToken();
+
+    UChar cc = m_inputStreamPreprocessor.nextInputCharacter();
+
+    // 4.8.10.13.4 WebVTT cue text tokenizer
+    switch (m_state) {
+    WEBVTT_BEGIN_STATE(DataState) {
+        if (cc == '&') {
+            m_buffer.append(cc);
+            WEBVTT_ADVANCE_TO(EscapeState);
+        } else if (cc == '<') {
+            if (m_token->type() == WebVTTTokenTypes::Uninitialized
+                || vectorEqualsString(m_token->characters(), emptyString()))
+                WEBVTT_ADVANCE_TO(TagState);
+            else
+                return emitAndResumeIn(source, WebVTTTokenizerState::TagState);
+        } else if (cc == InputStreamPreprocessor::endOfFileMarker)
+            return emitEndOfFile(source);
+        else {
+            bufferCharacter(cc);
+            WEBVTT_ADVANCE_TO(DataState);
+        }
+    }
+    END_STATE()
+
+    WEBVTT_BEGIN_STATE(EscapeState) {
+        if (cc == ';') {
+            if (vectorEqualsString(m_buffer, "&amp"))
+                bufferCharacter('&');
+            else if (vectorEqualsString(m_buffer, "&lt"))
+                bufferCharacter('<');
+            else if (vectorEqualsString(m_buffer, "&gt"))
+                bufferCharacter('>');
+            else {
+                m_buffer.append(cc);
+                m_token->appendToCharacter(m_buffer);
+            }
+            m_buffer.clear();
+            WEBVTT_ADVANCE_TO(DataState);
+        } else if (isASCIIAlphanumeric(cc)) {
+            m_buffer.append(cc);
+            WEBVTT_ADVANCE_TO(EscapeState);
+        } else if (cc == InputStreamPreprocessor::endOfFileMarker) {
+            m_token->appendToCharacter(m_buffer);
+            return emitEndOfFile(source);
+        } else {
+            if (!vectorEqualsString(m_buffer, "&"))
+                m_token->appendToCharacter(m_buffer);
+            m_buffer.clear();
+            WEBVTT_ADVANCE_TO(DataState);
+        }
+    }
+    END_STATE()
+
+    WEBVTT_BEGIN_STATE(TagState) {
+        if (isTokenizerWhitespace(cc)) {
+            m_token->beginEmptyStartTag();
+            WEBVTT_ADVANCE_TO(StartTagAnnotationState);
+        } else if (cc == '.') {
+            m_token->beginEmptyStartTag();
+            WEBVTT_ADVANCE_TO(StartTagClassState);
+        } else if (cc == '/') {
+            WEBVTT_ADVANCE_TO(EndTagOpenState);
+        } else if (WTF::isASCIIDigit(cc)) {
+            m_token->beginTimestampTag(cc);
+            WEBVTT_ADVANCE_TO(TimestampTagState);
+        } else if (cc == '>' || cc == InputStreamPreprocessor::endOfFileMarker) {
+            m_token->beginEmptyStartTag();
+            return emitAndResumeIn(source, WebVTTTokenizerState::DataState);
+        } else {
+            m_token->beginStartTag(cc);
+            WEBVTT_ADVANCE_TO(StartTagState);
+        }
+    }
+    END_STATE()
+
+    WEBVTT_BEGIN_STATE(StartTagState) {
+        if (isTokenizerWhitespace(cc))
+            WEBVTT_ADVANCE_TO(StartTagAnnotationState);
+        else if (cc == '.')
+            WEBVTT_ADVANCE_TO(StartTagClassState);
+        else if (cc == '>' || cc == InputStreamPreprocessor::endOfFileMarker)
+            return emitAndResumeIn(source, WebVTTTokenizerState::DataState);
+        else {
+            m_token->appendToName(cc);
+            WEBVTT_ADVANCE_TO(StartTagState);
+        }
+    }
+    END_STATE()
+
+    WEBVTT_BEGIN_STATE(StartTagClassState) {
+        if (isTokenizerWhitespace(cc)) {
+            m_token->addNewClass();
+            WEBVTT_ADVANCE_TO(StartTagAnnotationState);
+        } else if (cc == '.') {
+            m_token->addNewClass();
+            WEBVTT_ADVANCE_TO(StartTagClassState);
+        } else if (cc == '>' || cc == InputStreamPreprocessor::endOfFileMarker) {
+            m_token->addNewClass();
+            return emitAndResumeIn(source, WebVTTTokenizerState::DataState);
+        } else {
+            m_token->appendToClass(cc);
+            WEBVTT_ADVANCE_TO(StartTagClassState);
+        }
+
+    }
+    END_STATE()
+
+    WEBVTT_BEGIN_STATE(StartTagAnnotationState) {
+        if (cc == '>' || cc == InputStreamPreprocessor::endOfFileMarker) {
+            m_token->addNewAnnotation();
+            return emitAndResumeIn(source, WebVTTTokenizerState::DataState);
+        }
+        m_token->appendToAnnotation(cc);
+        WEBVTT_ADVANCE_TO(StartTagAnnotationState);
+    }
+    END_STATE()
+    
+    WEBVTT_BEGIN_STATE(EndTagOpenState) {
+        if (cc == '>' || cc == InputStreamPreprocessor::endOfFileMarker) {
+            m_token->beginEndTag('\0');
+            return emitAndResumeIn(source, WebVTTTokenizerState::DataState);
+        }
+        m_token->beginEndTag(cc);
+        WEBVTT_ADVANCE_TO(EndTagState);
+    }
+    END_STATE()
+
+    WEBVTT_BEGIN_STATE(EndTagState) {
+        if (cc == '>' || cc == InputStreamPreprocessor::endOfFileMarker)
+            return emitAndResumeIn(source, WebVTTTokenizerState::DataState);
+        m_token->appendToName(cc);
+        WEBVTT_ADVANCE_TO(EndTagState);
+    }
+    END_STATE()
+
+    WEBVTT_BEGIN_STATE(TimestampTagState) {
+        if (cc == '>' || cc == InputStreamPreprocessor::endOfFileMarker)
+            return emitAndResumeIn(source, WebVTTTokenizerState::DataState);
+        m_token->appendToTimestamp(cc);
+        WEBVTT_ADVANCE_TO(TimestampTagState);
+    }
+    END_STATE()
+
+    }
+
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+}
+
+#endif

Copied: trunk/Source/WebCore/platform/track/WebVTTTokenizer.h (from rev 94010, trunk/Source/WebCore/platform/track/CueParser.h) (0 => 94011)


--- trunk/Source/WebCore/platform/track/WebVTTTokenizer.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/track/WebVTTTokenizer.h	2011-08-29 20:47:06 UTC (rev 94011)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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 WebVTTTokenizer_h
+#define WebVTTTokenizer_h
+
+#if ENABLE(VIDEO_TRACK)
+
+#include "MarkupTokenizerBase.h"
+#include "SegmentedString.h"
+#include "WebVTTToken.h"
+
+namespace WebCore {
+
+class WebVTTTokenizerState {
+public:
+    enum State {
+        DataState,
+        EscapeState,
+        TagState,
+        StartTagState,
+        StartTagClassState,
+        StartTagAnnotationState,
+        EndTagState,
+        EndTagOpenState,
+        TimestampTagState,
+    };
+};
+
+class WebVTTTokenizer : MarkupTokenizerBase<WebVTTToken, WebVTTTokenizerState> {
+    WTF_MAKE_NONCOPYABLE(WebVTTTokenizer);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<WebVTTTokenizer> create() { return adoptPtr(new WebVTTTokenizer); }
+
+    void reset();
+    
+    bool nextToken(SegmentedString&, WebVTTToken&);
+
+private:
+    WebVTTTokenizer();
+    
+    Vector<UChar, 32> m_buffer;
+};
+
+}
+
+#endif
+#endif
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to