Esempio n. 1
0
void ContentDistributor::distribute(Element* host)
{
    ASSERT(needsDistribution());
    ASSERT(m_nodeToInsertionPoint.isEmpty());
    ASSERT(!host->containingShadowRoot() || host->containingShadowRoot()->owner()->distributor().isValid());

    m_validity = Valid;

    ContentDistribution pool;
    for (Node* node = host->firstChild(); node; node = node->nextSibling())
        populate(node, pool);

    Vector<bool> distributed(pool.size());
    distributed.fill(false);

    if (ShadowRoot* root = host->shadowRoot()) {
        if (ScopeContentDistribution* scope = root->scopeDistribution()) {
            const Vector<RefPtr<InsertionPoint> >& insertionPoints = scope->ensureInsertionPointList(root);
            for (size_t i = 0; i < insertionPoints.size(); ++i) {
                InsertionPoint* point = insertionPoints[i].get();
                if (!point->isActive())
                    continue;

                distributeSelectionsTo(point, pool, distributed);
                if (ElementShadow* shadow = point->parentNode()->isElementNode() ? toElement(point->parentNode())->shadow() : 0)
                    shadow->invalidateDistribution();
            }
        }
    }
}
void ContentDistributor::distributeNodeChildrenTo(InsertionPoint* insertionPoint, ContainerNode* containerNode)
{
    ContentDistribution distribution;
    for (Node* node = containerNode->firstChild(); node; node = node->nextSibling()) {
        if (isActiveInsertionPoint(node)) {
            InsertionPoint* innerInsertionPoint = toInsertionPoint(node);
            if (innerInsertionPoint->hasDistribution()) {
                for (size_t i = 0; i < innerInsertionPoint->size(); ++i) {
                    distribution.append(innerInsertionPoint->at(i));
                    if (!m_nodeToInsertionPoint.contains(innerInsertionPoint->at(i)))
                        m_nodeToInsertionPoint.add(innerInsertionPoint->at(i), insertionPoint);
                }
            } else {
                for (Node* child = innerInsertionPoint->firstChild(); child; child = child->nextSibling()) {
                    distribution.append(child);
                    m_nodeToInsertionPoint.add(child, insertionPoint);
                }
            }
        } else {
            distribution.append(node);
            if (!m_nodeToInsertionPoint.contains(node))
                m_nodeToInsertionPoint.add(node, insertionPoint);
        }
    }

    insertionPoint->setDistribution(distribution);
}
Esempio n. 3
0
void DistributionPool::distributeTo(InsertionPoint* insertionPoint, ElementShadow* elementShadow)
{
    ContentDistribution distribution;

    for (size_t i = 0; i < m_nodes.size(); ++i) {
        if (m_distributed[i])
            continue;

        if (isHTMLContentElement(*insertionPoint) && !toHTMLContentElement(insertionPoint)->canSelectNode(m_nodes, i))
            continue;

        Node* node = m_nodes[i];
        distribution.append(node);
        elementShadow->didDistributeNode(node, insertionPoint);
        m_distributed[i] = true;
    }

    // Distributes fallback elements
    if (insertionPoint->isContentInsertionPoint() && distribution.isEmpty()) {
        for (Node* fallbackNode = insertionPoint->firstChild(); fallbackNode; fallbackNode = fallbackNode->nextSibling()) {
            distribution.append(fallbackNode);
            elementShadow->didDistributeNode(fallbackNode, insertionPoint);
        }
    }
    insertionPoint->setDistribution(distribution);
}
void ContentDistributor::distribute(Element* host)
{
    ASSERT(needsDistribution());
    ASSERT(m_nodeToInsertionPoint.isEmpty());

    m_validity = Valid;

    ContentDistribution pool;
    for (Node* node = host->firstChild(); node; node = node->nextSibling())
        populate(node, pool);

    Vector<bool> distributed(pool.size());
    distributed.fill(false);

    Vector<HTMLShadowElement*, 8> activeShadowInsertionPoints;
    for (ShadowRoot* root = host->youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        HTMLShadowElement* firstActiveShadowInsertionPoint = 0;

        const Vector<InsertionPoint*>& insertionPoints = root->insertionPointList();
        for (size_t i = 0; i < insertionPoints.size(); ++i) {
            InsertionPoint* point = insertionPoints[i];
            if (!point->isActive())
                continue;

            if (isHTMLShadowElement(point)) {
                if (!firstActiveShadowInsertionPoint)
                    firstActiveShadowInsertionPoint = toHTMLShadowElement(point);
            } else {
                distributeSelectionsTo(point, pool, distributed);
                if (ElementShadow* shadow = point->parentNode()->isElementNode() ? toElement(point->parentNode())->shadow() : 0)
                    shadow->invalidateDistribution();
            }
        }

        if (firstActiveShadowInsertionPoint)
            activeShadowInsertionPoints.append(firstActiveShadowInsertionPoint);
    }

    for (size_t i = activeShadowInsertionPoints.size(); i > 0; --i) {
        HTMLShadowElement* shadowElement = activeShadowInsertionPoints[i - 1];
        ShadowRoot* root = shadowElement->shadowRoot();
        ASSERT(root);
        if (root->olderShadowRoot()) {
            distributeNodeChildrenTo(shadowElement, root->olderShadowRoot());
            root->olderShadowRoot()->setAssignedTo(shadowElement);
        } else {
            distributeSelectionsTo(shadowElement, pool, distributed);
            if (ElementShadow* shadow = shadowElement->parentNode()->isElementNode() ? toElement(shadowElement->parentNode())->shadow() : 0)
                shadow->invalidateDistribution();
        }
    }
}
Esempio n. 5
0
void ContentDistributor::populate(Node* node, ContentDistribution& pool)
{
    if (!isActiveInsertionPoint(node)) {
        pool.append(node);
        return;
    }

    InsertionPoint* insertionPoint = toInsertionPoint(node);
    if (insertionPoint->hasDistribution()) {
        for (size_t i = 0; i < insertionPoint->size(); ++i)
            populate(insertionPoint->at(i), pool);
    } else {
        for (Node* fallbackNode = insertionPoint->firstChild(); fallbackNode; fallbackNode = fallbackNode->nextSibling())
            pool.append(fallbackNode);
    }
}
Esempio n. 6
0
void ContentDistributor::distributeSelectionsTo(InsertionPoint* insertionPoint, const ContentDistribution& pool, Vector<bool>& distributed)
{
    ContentDistribution distribution;

    for (size_t i = 0; i < pool.size(); ++i) {
        if (distributed[i])
            continue;

        if (insertionPoint->matchTypeFor(pool.nodes().at(i).get()) != InsertionPoint::AlwaysMatches)
            continue;

        Node* child = pool.at(i).get();
        distribution.append(child);
        m_nodeToInsertionPoint.add(child, insertionPoint);
        distributed[i] = true;
    }

    insertionPoint->setDistribution(distribution);
}
void ContentDistributor::distributeSelectionsTo(InsertionPoint* insertionPoint, const ContentDistribution& pool, Vector<bool>& distributed)
{
    ContentDistribution distribution;
    ContentSelectorQuery query(insertionPoint);

    for (size_t i = 0; i < pool.size(); ++i) {
        if (distributed[i])
            continue;

        if (!query.matches(pool.nodes(), i))
            continue;

        Node* child = pool.at(i).get();
        distribution.append(child);
        m_nodeToInsertionPoint.add(child, insertionPoint);
        distributed[i] = true;
    }

    insertionPoint->setDistribution(distribution);
}
Esempio n. 8
0
void InsertionPoint::setDistribution(ContentDistribution& distribution)
{
    if (shouldUseFallbackElements()) {
        for (Node* child = firstChild(); child; child = child->nextSibling())
            child->lazyReattachIfAttached();
    }

    // Attempt not to reattach nodes that would be distributed to the exact same
    // location by comparing the old and new distributions.

    size_t i = 0;
    size_t j = 0;

    for ( ; i < m_distribution.size() && j < distribution.size(); ++i, ++j) {
        if (m_distribution.size() < distribution.size()) {
            // If the new distribution is larger than the old one, reattach all nodes in
            // the new distribution that were inserted.
            for ( ; j < distribution.size() && m_distribution.at(i) != distribution.at(j); ++j)
                distribution.at(j)->lazyReattachIfAttached();
        } else if (m_distribution.size() > distribution.size()) {
            // If the old distribution is larger than the new one, reattach all nodes in
            // the old distribution that were removed.
            for ( ; i < m_distribution.size() && m_distribution.at(i) != distribution.at(j); ++i)
                m_distribution.at(i)->lazyReattachIfAttached();
        } else if (m_distribution.at(i) != distribution.at(j)) {
            // If both distributions are the same length reattach both old and new.
            m_distribution.at(i)->lazyReattachIfAttached();
            distribution.at(j)->lazyReattachIfAttached();
        }
    }

    // If we hit the end of either list above we need to reattach all remaining nodes.

    for ( ; i < m_distribution.size(); ++i)
        m_distribution.at(i)->lazyReattachIfAttached();

    for ( ; j < distribution.size(); ++j)
        distribution.at(j)->lazyReattachIfAttached();

    m_distribution.swap(distribution);
    m_distribution.shrinkToFit();
}