예제 #1
0
파일: VTTCue.cpp 프로젝트: kjthegod/WebKit
void VTTCue::markFutureAndPastNodes(ContainerNode* root, double previousTimestamp, double movieTime)
{
    DEFINE_STATIC_LOCAL(const String, timestampTag, ("timestamp"));

    bool isPastNode = true;
    double currentTimestamp = previousTimestamp;
    if (currentTimestamp > movieTime)
        isPastNode = false;

    for (Node& child : NodeTraversal::descendantsOf(*root)) {
        if (child.nodeName() == timestampTag) {
            double currentTimestamp;
            bool check = VTTParser::collectTimeStamp(child.nodeValue(), currentTimestamp);
            ASSERT_UNUSED(check, check);

            if (currentTimestamp > movieTime)
                isPastNode = false;
        }

        if (child.isVTTElement()) {
            toVTTElement(child).setIsPastNode(isPastNode);
            // Make an elemenet id match a cue id for style matching purposes.
            if (!id().isEmpty())
                toElement(child).setIdAttribute(id());
        }
    }
}
예제 #2
0
파일: VTTCue.cpp 프로젝트: kjthegod/WebKit
static CSSValueID determineTextDirection(DocumentFragment* vttRoot)
{
    ASSERT(vttRoot);

    // Apply the Unicode Bidirectional Algorithm's Paragraph Level steps to the
    // concatenation of the values of each WebVTT Text Object in nodes, in a
    // pre-order, depth-first traversal, excluding WebVTT Ruby Text Objects and
    // their descendants.
    TextDirection textDirection = LTR;
    Node* node = NodeTraversal::next(*vttRoot);
    while (node) {
        ASSERT(node->isDescendantOf(vttRoot));

        if (node->isTextNode()) {
            bool hasStrongDirectionality;
            textDirection = determineDirectionality(node->nodeValue(), hasStrongDirectionality);
            if (hasStrongDirectionality)
                break;
        } else if (node->isVTTElement()) {
            if (toVTTElement(node)->webVTTNodeType() == VTTNodeTypeRubyText) {
                node = NodeTraversal::nextSkippingChildren(*node);
                continue;
            }
        }

        node = NodeTraversal::next(*node);
    }
    return isLeftToRightDirection(textDirection) ? CSSValueLtr : CSSValueRtl;
}
예제 #3
0
파일: VTTCue.cpp 프로젝트: Igalia/blink
void VTTCue::markFutureAndPastNodes(ContainerNode* root, double previousTimestamp, double movieTime)
{
    DEFINE_STATIC_LOCAL(const String, timestampTag, ("timestamp"));

    bool isPastNode = true;
    double currentTimestamp = previousTimestamp;
    if (currentTimestamp > movieTime)
        isPastNode = false;

    for (Node* child = root->firstChild(); child; child = NodeTraversal::next(*child, root)) {
        if (child->nodeName() == timestampTag) {
            unsigned position = 0;
            String timestamp = child->nodeValue();
            double currentTimestamp;
            bool check = VTTParser::collectTimeStamp(timestamp, &position, currentTimestamp);
            ASSERT_UNUSED(check, check);

            if (currentTimestamp > movieTime)
                isPastNode = false;
        }

        if (child->isVTTElement()) {
            toVTTElement(child)->setIsPastNode(isPastNode);
            // Make an elemenet id match a cue id for style matching purposes.
            if (!id().isEmpty())
                toElement(child)->setIdAttribute(id());
        }
    }
}
예제 #4
0
파일: VTTCue.cpp 프로젝트: kjthegod/WebKit
void VTTCue::copyVTTNodeToDOMTree(ContainerNode* vttNode, ContainerNode* parent)
{
    for (Node* node = vttNode->firstChild(); node; node = node->nextSibling()) {
        RefPtrWillBeRawPtr<Node> clonedNode;
        if (node->isVTTElement())
            clonedNode = toVTTElement(node)->createEquivalentHTMLElement(document());
        else
            clonedNode = node->cloneNode(false);
        parent->appendChild(clonedNode);
        if (node->isContainerNode())
            copyVTTNodeToDOMTree(toContainerNode(node), toContainerNode(clonedNode));
    }
}
예제 #5
0
void VTTCue::updatePastAndFutureNodes(double movieTime)
{
    DEFINE_STATIC_LOCAL(const String, timestampTag, ("timestamp"));

    ASSERT(isActive());

    // An active cue may still not have a display tree, e.g. if its track is
    // hidden or if the track belongs to an audio element.
    if (!m_displayTree)
        return;

    // FIXME: Per spec it's possible for neither :past nor :future to match, but
    // as implemented here and in SelectorChecker they are simply each others
    // negations. For a cue with no internal timestamps, :past will match but
    // should not per spec. :future is correct, however. See the spec bug to
    // determine what the correct behavior should be:
    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28237

    bool isPastNode = true;
    double currentTimestamp = startTime();
    if (currentTimestamp > movieTime)
        isPastNode = false;

    for (Node& child : NodeTraversal::descendantsOf(*m_displayTree)) {
        if (child.nodeName() == timestampTag) {
            double currentTimestamp;
            bool check = VTTParser::collectTimeStamp(child.nodeValue(), currentTimestamp);
            ASSERT_UNUSED(check, check);

            if (currentTimestamp > movieTime)
                isPastNode = false;
        }

        if (child.isVTTElement()) {
            toVTTElement(child).setIsPastNode(isPastNode);
            // Make an elemenet id match a cue id for style matching purposes.
            if (!id().isEmpty())
                toElement(child).setIdAttribute(id());
        }
    }
}
예제 #6
0
void VTTTreeBuilder::constructTreeFromToken(Document& document)
{
    // http://dev.w3.org/html5/webvtt/#webvtt-cue-text-dom-construction-rules

    switch (m_token.type()) {
    case VTTTokenTypes::Character: {
        m_currentNode->parserAppendChild(Text::create(document, m_token.characters()));
        break;
    }
    case VTTTokenTypes::StartTag: {
        VTTNodeType nodeType = tokenToNodeType(m_token);
        if (nodeType == VTTNodeTypeNone)
            break;

        VTTNodeType currentType = m_currentNode->isVTTElement() ? toVTTElement(m_currentNode.get())->webVTTNodeType() : VTTNodeTypeNone;
        // <rt> is only allowed if the current node is <ruby>.
        if (nodeType == VTTNodeTypeRubyText && currentType != VTTNodeTypeRuby)
            break;

        RefPtrWillBeRawPtr<VTTElement> child = VTTElement::create(nodeType, &document);
        if (!m_token.classes().isEmpty())
            child->setAttribute(classAttr, m_token.classes());

        if (nodeType == VTTNodeTypeVoice) {
            child->setAttribute(VTTElement::voiceAttributeName(), m_token.annotation());
        } else if (nodeType == VTTNodeTypeLanguage) {
            m_languageStack.append(m_token.annotation());
            child->setAttribute(VTTElement::langAttributeName(), m_languageStack.last());
        }
        if (!m_languageStack.isEmpty())
            child->setLanguage(m_languageStack.last());
        m_currentNode->parserAppendChild(child);
        m_currentNode = child;
        break;
    }
    case VTTTokenTypes::EndTag: {
        VTTNodeType nodeType = tokenToNodeType(m_token);
        if (nodeType == VTTNodeTypeNone)
            break;

        // The only non-VTTElement would be the DocumentFragment root. (Text
        // nodes and PIs will never appear as m_currentNode.)
        if (!m_currentNode->isVTTElement())
            break;

        VTTNodeType currentType = toVTTElement(m_currentNode.get())->webVTTNodeType();
        bool matchesCurrent = nodeType == currentType;
        if (!matchesCurrent) {
            // </ruby> auto-closes <rt>.
            if (currentType == VTTNodeTypeRubyText && nodeType == VTTNodeTypeRuby) {
                if (m_currentNode->parentNode())
                    m_currentNode = m_currentNode->parentNode();
            } else {
                break;
            }
        }
        if (nodeType == VTTNodeTypeLanguage)
            m_languageStack.removeLast();
        if (m_currentNode->parentNode())
            m_currentNode = m_currentNode->parentNode();
        break;
    }
    case VTTTokenTypes::TimestampTag: {
        String charactersString = m_token.characters();
        double parsedTimeStamp;
        if (VTTParser::collectTimeStamp(charactersString, parsedTimeStamp))
            m_currentNode->parserAppendChild(ProcessingInstruction::create(document, "timestamp", charactersString));
        break;
    }
    default:
        break;
    }
}