예제 #1
0
void RenderTreeUpdater::createRenderer(Element& element, RenderStyle&& style)
{
    auto computeInsertionPosition = [this, &element, &style] () {
#if ENABLE(CSS_REGIONS)
        if (element.shouldMoveToFlowThread(style))
            return RenderTreePosition::insertionPositionForFlowThread(renderTreePosition().parent().element(), element, style);
#endif
        renderTreePosition().computeNextSibling(element);
        return renderTreePosition();
    };
    
    if (!shouldCreateRenderer(element, renderTreePosition().parent()))
        return;

#if ENABLE(CSS_REGIONS)
    // Even display: none elements need to be registered in FlowThreadController.
    registerElementForFlowThreadIfNeeded(element, style);
#endif

    if (!element.rendererIsNeeded(style))
        return;

    RenderTreePosition insertionPosition = computeInsertionPosition();
    RenderElement* newRenderer = element.createElementRenderer(WTFMove(style), insertionPosition).leakPtr();
    if (!newRenderer)
        return;
    if (!insertionPosition.canInsert(*newRenderer)) {
        newRenderer->destroy();
        return;
    }

    // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
    // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
    newRenderer->setFlowThreadState(insertionPosition.parent().flowThreadState());

    element.setRenderer(newRenderer);

    auto& initialStyle = newRenderer->style();
    std::unique_ptr<RenderStyle> animatedStyle;
    newRenderer->animation().updateAnimations(*newRenderer, initialStyle, animatedStyle);
    if (animatedStyle)
        newRenderer->setStyleInternal(WTFMove(*animatedStyle));

    newRenderer->initializeStyle();

#if ENABLE(FULLSCREEN_API)
    if (m_document.webkitIsFullScreen() && m_document.webkitCurrentFullScreenElement() == &element) {
        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, &insertionPosition.parent(), m_document);
        if (!newRenderer)
            return;
    }
#endif
    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    insertionPosition.insert(*newRenderer);

    if (AXObjectCache* cache = m_document.axObjectCache())
        cache->updateCacheAfterNodeIsAttached(&element);
}
예제 #2
0
void RenderTreeUpdater::updateTextRenderer(Text& text)
{
    bool hasRenderer = text.renderer();
    bool needsRenderer = textRendererIsNeeded(text, renderTreePosition());
    if (hasRenderer) {
        if (needsRenderer)
            return;
        tearDownRenderer(text);
        invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text);
        return;
    }
    if (!needsRenderer)
        return;
    createTextRenderer(text, renderTreePosition());
    invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text);
}
예제 #3
0
void RenderTreeUpdater::updateRenderTree(ContainerNode& root)
{
    ASSERT(root.renderer());
    ASSERT(m_parentStack.isEmpty());

    m_parentStack.append(Parent(root));

    auto descendants = composedTreeDescendants(root);
    auto it = descendants.begin();
    auto end = descendants.end();

    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=156172
    it.dropAssertions();

    while (it != end) {
        popParentsToDepth(it.depth());

        auto& node = *it;

        if (auto* renderer = node.renderer())
            renderTreePosition().invalidateNextSibling(*renderer);

        if (is<Text>(node)) {
            auto& text = downcast<Text>(node);
            if (parent().styleChange == Style::Detach || m_styleUpdate->textUpdate(text) || m_invalidatedWhitespaceOnlyTextSiblings.contains(&text))
                updateTextRenderer(text);

            it.traverseNextSkippingChildren();
            continue;
        }

        auto& element = downcast<Element>(node);

        auto* elementUpdate = m_styleUpdate->elementUpdate(element);
        if (!elementUpdate) {
            it.traverseNextSkippingChildren();
            continue;
        }

        updateElementRenderer(element, *elementUpdate);

        bool mayHaveRenderedDescendants = element.renderer() || (element.hasDisplayContents() && shouldCreateRenderer(element, renderTreePosition().parent()));
        if (!mayHaveRenderedDescendants) {
            it.traverseNextSkippingChildren();
            continue;
        }

        pushParent(element, elementUpdate ? elementUpdate->change : Style::NoChange);

        it.traverseNext();
    }

    popParentsToDepth(0);

    m_invalidatedWhitespaceOnlyTextSiblings.clear();
}
예제 #4
0
void RenderTreeUpdater::updateBeforeOrAfterPseudoElement(Element& current, PseudoId pseudoId)
{
    PseudoElement* pseudoElement = pseudoId == BEFORE ? current.beforePseudoElement() : current.afterPseudoElement();

    if (auto* renderer = pseudoElement ? pseudoElement->renderer() : nullptr)
        renderTreePosition().invalidateNextSibling(*renderer);

    bool needsPseudoElement = WebCore::needsPseudoElement(current, pseudoId);
    if (!needsPseudoElement) {
        if (pseudoElement) {
            if (pseudoId == BEFORE)
                current.clearBeforePseudoElement();
            else
                current.clearAfterPseudoElement();
        }
        return;
    }

    RefPtr<PseudoElement> newPseudoElement;
    if (!pseudoElement) {
        newPseudoElement = PseudoElement::create(current, pseudoId);
        pseudoElement = newPseudoElement.get();
    }

    auto newStyle = RenderStyle::clonePtr(*current.renderer()->getCachedPseudoStyle(pseudoId, &current.renderer()->style()));

    auto elementUpdate = Style::TreeResolver::createAnimatedElementUpdate(WTFMove(newStyle), *pseudoElement, Style::NoChange);

    if (elementUpdate.change == Style::NoChange)
        return;

    if (newPseudoElement) {
        InspectorInstrumentation::pseudoElementCreated(m_document.page(), *newPseudoElement);
        if (pseudoId == BEFORE)
            current.setBeforePseudoElement(newPseudoElement.releaseNonNull());
        else
            current.setAfterPseudoElement(newPseudoElement.releaseNonNull());
    }

    updateElementRenderer(*pseudoElement, elementUpdate);

    if (elementUpdate.change == Style::Detach)
        pseudoElement->didAttachRenderers();
    else
        pseudoElement->didRecalcStyle(elementUpdate.change);
}
예제 #5
0
void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::ElementUpdate& update)
{
#if PLATFORM(IOS)
    CheckForVisibilityChange checkForVisibilityChange(element);
#endif

    bool shouldTearDownRenderers = update.change == Style::Detach && (element.renderer() || element.isNamedFlowContentElement());
    if (shouldTearDownRenderers)
        tearDownRenderers(element, TeardownType::KeepHoverAndActive);

    bool hasDisplayContents = update.style->display() == CONTENTS;
    if (hasDisplayContents != element.hasDisplayContents()) {
        element.setHasDisplayContents(hasDisplayContents);
        // Render tree position needs to be recomputed as rendering siblings may be found from the display:contents subtree.
        renderTreePosition().invalidateNextSibling();
    }

    bool shouldCreateNewRenderer = !element.renderer() && !hasDisplayContents;
    if (shouldCreateNewRenderer) {
        if (element.hasCustomStyleResolveCallbacks())
            element.willAttachRenderers();
        createRenderer(element, RenderStyle::clone(*update.style));
        invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(element);
        return;
    }

    if (!element.renderer())
        return;
    auto& renderer = *element.renderer();

    if (update.recompositeLayer) {
        renderer.setStyle(RenderStyle::clone(*update.style), StyleDifferenceRecompositeLayer);
        return;
    }

    if (update.change == Style::NoChange) {
        if (pseudoStyleCacheIsInvalid(&renderer, update.style.get())) {
            renderer.setStyle(RenderStyle::clone(*update.style), StyleDifferenceEqual);
            return;
        }
        return;
    }

    renderer.setStyle(RenderStyle::clone(*update.style), StyleDifferenceEqual);
}
예제 #6
0
void RenderTreeUpdater::updateElementRenderer(Element& element, Style::ElementUpdate& update)
{
    bool shouldTearDownRenderers = update.change == Style::Detach && (element.renderer() || element.isNamedFlowContentNode());
    if (shouldTearDownRenderers)
        tearDownRenderers(element, TeardownType::KeepHoverAndActive);

    bool hasDisplayContest = update.style && update.style->display() == CONTENTS;
    if (hasDisplayContest != element.hasDisplayContents()) {
        element.setHasDisplayContents(hasDisplayContest);
        // Render tree position needs to be recomputed as rendering siblings may be found from the display:contents subtree.
        renderTreePosition().invalidateNextSibling();
    }

    bool shouldCreateNewRenderer = !element.renderer() && update.style && !hasDisplayContest;
    if (shouldCreateNewRenderer) {
        if (element.hasCustomStyleResolveCallbacks())
            element.willAttachRenderers();
        createRenderer(element, WTFMove(*update.style));
        invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(element);
        return;
    }

    if (!element.renderer())
        return;
    auto& renderer = *element.renderer();

    if (update.isSynthetic) {
        renderer.setStyle(WTFMove(*update.style), StyleDifferenceRecompositeLayer);
        return;
    }

    if (update.change == Style::NoChange) {
        if (pseudoStyleCacheIsInvalid(&renderer, update.style.get()) || (parent().styleChange == Style::Force && renderer.requiresForcedStyleRecalcPropagation())) {
            renderer.setStyle(WTFMove(*update.style), StyleDifferenceEqual);
            return;
        }
        return;
    }

    renderer.setStyle(WTFMove(*update.style), StyleDifferenceEqual);
}