Пример #1
0
void Text::reattachIfNeeded(const AttachContext& context)
{
    bool layoutObjectIsNeeded = false;
    ContainerNode* layoutParent = LayoutTreeBuilderTraversal::parent(*this);
    if (layoutParent) {
        if (LayoutObject* parentLayoutObject = layoutParent->layoutObject()) {
            if (textLayoutObjectIsNeeded(*parentLayoutObject->style(), *parentLayoutObject))
                layoutObjectIsNeeded = true;
        }
    }

    if (layoutObjectIsNeeded == !!layoutObject())
        return;

    // The following is almost the same as Node::reattach() except that we create a layoutObject only if needed.
    // Not calling reattach() to avoid repeated calls to Text::textLayoutObjectIsNeeded().
    AttachContext reattachContext(context);
    reattachContext.performingReattach = true;

    if (styleChangeType() < NeedsReattachStyleChange)
        detach(reattachContext);
    if (layoutObjectIsNeeded)
        LayoutTreeBuilderForText(*this, layoutParent->layoutObject()).createLayoutObject();
    CharacterData::attach(reattachContext);
}
Пример #2
0
void Text::reattachIfNeeded(const AttachContext& context)
{
    bool rendererIsNeeded = false;
    ContainerNode* renderingParent = NodeRenderingTraversal::parent(*this);
    if (renderingParent) {
        if (RenderObject* parentRenderer = renderingParent->renderer()) {
            if (textRendererIsNeeded(*parentRenderer->style(), *parentRenderer))
                rendererIsNeeded = true;
        }
    }

    if (rendererIsNeeded == !!renderer())
        return;

    // The following is almost the same as Node::reattach() except that we create renderer only if needed.
    // Not calling reattach() to avoid repeated calls to Text::textRendererIsNeeded().
    AttachContext reattachContext(context);
    reattachContext.performingReattach = true;

    if (styleChangeType() < NeedsReattachStyleChange)
        detach(reattachContext);
    if (rendererIsNeeded)
        RenderTreeBuilderForText(*this, renderingParent->renderer()).createRenderer();
    CharacterData::attach(reattachContext);
}
Пример #3
0
StyleRecalcChange Element::recalcOwnStyle(StyleRecalcChange change)
{
    ASSERT(document().inStyleRecalc());
    ASSERT(!parentNode()->needsStyleRecalc());
    ASSERT(change >= Inherit || needsStyleRecalc());
    ASSERT(parentRenderStyle());

    RefPtr<RenderStyle> oldStyle = renderStyle();
    RefPtr<RenderStyle> newStyle = styleForRenderer();
    StyleRecalcChange localChange = RenderStyle::stylePropagationDiff(oldStyle.get(), newStyle.get());

    ASSERT(newStyle);

    if (localChange == Reattach) {
        AttachContext reattachContext;
        reattachContext.resolvedStyle = newStyle.get();
        reattach(reattachContext);
        return Reattach;
    }

    ASSERT(oldStyle);

    if (RenderObject* renderer = this->renderer()) {
        if (localChange != NoChange)
            renderer->setStyle(newStyle.get());
    }

    if (styleChangeType() >= SubtreeStyleChange)
        return Force;

    if (change > Inherit || localChange > Inherit)
        return max(localChange, change);

    return localChange;
}
Пример #4
0
void ShadowRoot::recalcStyle(StyleRecalcChange change)
{
    // ShadowRoot doesn't support custom callbacks.
    ASSERT(!hasCustomStyleCallbacks());

    StyleResolverParentScope parentScope(*this);

    if (styleChangeType() >= SubtreeStyleChange)
        change = Force;

    if (change < Force && hasRareData() && childNeedsStyleRecalc())
        checkForChildrenAdjacentRuleChanges();

    // There's no style to update so just calling recalcStyle means we're updated.
    clearNeedsStyleRecalc();

    // FIXME: This doesn't handle :hover + div properly like Element::recalcStyle does.
    Text* lastTextNode = 0;
    for (Node* child = lastChild(); child; child = child->previousSibling()) {
        if (child->isTextNode()) {
            toText(child)->recalcTextStyle(change, lastTextNode);
            lastTextNode = toText(child);
        } else if (child->isElementNode()) {
            if (child->shouldCallRecalcStyle(change))
                toElement(child)->recalcStyle(change, lastTextNode);
            if (child->renderer())
                lastTextNode = 0;
        }
    }

    clearChildNeedsStyleRecalc();
}
Пример #5
0
void SVGElement::willRecalcStyle(StyleChange change)
{
    if (!hasSVGRareData() || styleChangeType() == SyntheticStyleChange)
        return;
    // If the style changes because of a regular property change (not induced by SMIL animations themselves)
    // reset the "computed style without SMIL style properties", so the base value change gets reflected.
    if (change > NoChange || needsStyleRecalc())
        svgRareData()->setNeedsOverrideComputedStyleUpdate();
}
Пример #6
0
void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
{
    if (name == HTMLNames::idAttr)
        updateId(oldValue, newValue);

    if (inActiveDocument() && styleChangeType() < SubtreeStyleChange && affectedByAttributeSelector(name.localName()))
        setNeedsStyleRecalc(LocalStyleChange);

    if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(*this, name))
        recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue));
}
Пример #7
0
void Element::classAttributeChanged(const AtomicString& newClassString)
{
    bool testShouldInvalidateStyle = inActiveDocument() && styleChangeType() < SubtreeStyleChange;

    ASSERT(elementData());
    const SpaceSplitString oldClasses = elementData()->classNames();
    elementData()->setClass(newClassString, false);
    const SpaceSplitString& newClasses = elementData()->classNames();
    if (testShouldInvalidateStyle && classChangeNeedsStyleRecalc(oldClasses, newClasses))
        setNeedsStyleRecalc(LocalStyleChange);
    if (!newClasses.size())
        elementData()->clearClass();
}
Пример #8
0
void Element::attach(const AttachContext& context)
{
    ASSERT(document().inStyleRecalc());

    // We've already been through detach when doing an attach, but we might
    // need to clear any state that's been added since then.
    if (hasRareData() && styleChangeType() == NeedsReattachStyleChange) {
        ElementRareData* data = elementRareData();
        data->clearComputedStyle();
    }

    RenderTreeBuilder(this, context.resolvedStyle).createRendererForElementIfNeeded();

    ContainerNode::attach(context);
}
Пример #9
0
void ShadowRoot::recalcStyle(StyleRecalcChange change)
{
    // ShadowRoot doesn't support custom callbacks.
    ASSERT(!hasCustomStyleCallbacks());

    StyleResolverParentScope parentScope(*this);

    if (styleChangeType() >= SubtreeStyleChange)
        change = Force;

    // There's no style to update so just calling recalcStyle means we're updated.
    clearNeedsStyleRecalc();

    recalcChildStyle(change);
    clearChildNeedsStyleRecalc();
}
Пример #10
0
void ShadowRoot::recalcStyle(StyleRecalcChange change)
{
    if (styleChangeType() >= SubtreeStyleChange)
        change = Force;

    // There's no style to update so just calling recalcStyle means we're updated.
    clearNeedsStyleRecalc();

    for (Node* child = lastChild(); child; child = child->previousSibling()) {
        if (child->isTextNode()) {
            toText(child)->recalcTextStyle(change);
        } else if (child->isElementNode()) {
            if (child->shouldCallRecalcStyle(change))
                toElement(child)->recalcStyle(change);
        }
    }

    clearChildNeedsStyleRecalc();
}
Пример #11
0
void Element::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason)
{
    bool testShouldInvalidateStyle = inActiveDocument() && styleChangeType() < SubtreeStyleChange;

    if (isStyledElement() && name == HTMLNames::styleAttr) {
        styleAttributeChanged(newValue);
    }

    if (name == HTMLNames::idAttr) {
        AtomicString oldId = elementData()->idForStyleResolution();
        AtomicString newId = newValue;
        if (newId != oldId) {
            elementData()->setIdForStyleResolution(newId);
            if (testShouldInvalidateStyle && (affectedByIdSelector(oldId) || affectedByIdSelector(newId)))
                setNeedsStyleRecalc(LocalStyleChange);
        }
    } else if (name == HTMLNames::classAttr) {
        classAttributeChanged(newValue);
    }
}
void Element::recalcStyle(StyleChange change)
{
    RenderStyle* currentStyle = renderStyle();
    bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
    bool hasPositionalRules = changed() && currentStyle && currentStyle->childrenAffectedByPositionalRules();
    bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();

#if ENABLE(SVG)
    if (!hasParentStyle && isShadowNode() && isSVGElement())
        hasParentStyle = true;
#endif

    if ((change > NoChange || changed())) {
        if (hasRareData())
            rareData()->resetComputedStyle();
    }
    if (hasParentStyle && (change >= Inherit || changed())) {
        RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this);
        StyleChange ch = diff(currentStyle, newStyle.get());
        if (ch == Detach || !currentStyle) {
            if (attached())
                detach();
            attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
            // attach recalulates the style for all children. No need to do it twice.
            setChanged(NoStyleChange);
            setHasChangedChild(false);
            return;
        }

        if (currentStyle) {
            // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
            // style change (e.g., only inline style changed).
            if (currentStyle->affectedByHoverRules())
                newStyle->setAffectedByHoverRules(true);
            if (currentStyle->affectedByActiveRules())
                newStyle->setAffectedByActiveRules(true);
            if (currentStyle->affectedByDragRules())
                newStyle->setAffectedByDragRules(true);
            if (currentStyle->childrenAffectedByForwardPositionalRules())
                newStyle->setChildrenAffectedByForwardPositionalRules();
            if (currentStyle->childrenAffectedByBackwardPositionalRules())
                newStyle->setChildrenAffectedByBackwardPositionalRules();
            if (currentStyle->childrenAffectedByFirstChildRules())
                newStyle->setChildrenAffectedByFirstChildRules();
            if (currentStyle->childrenAffectedByLastChildRules())
                newStyle->setChildrenAffectedByLastChildRules();
            if (currentStyle->childrenAffectedByDirectAdjacentRules())
                newStyle->setChildrenAffectedByDirectAdjacentRules();
        }

        if (ch != NoChange) {
            setRenderStyle(newStyle);
        } else if (changed() && (styleChangeType() != AnimationStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
            // Although no change occurred, we use the new style so that the cousin style sharing code won't get
            // fooled into believing this style is the same.  This is only necessary if the document actually uses
            // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
            // descendants.
            if (renderer())
                renderer()->setStyleInternal(newStyle.get());
            else
                setRenderStyle(newStyle);
        } else if (styleChangeType() == AnimationStyleChange)
             setRenderStyle(newStyle);

        if (change != Force) {
            if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange)
                change = Force;
            else
                change = ch;
        }
    }

    // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
    // For now we will just worry about the common case, since it's a lot trickier to get the second case right
    // without doing way too much re-resolution.
    bool forceCheckOfNextElementSibling = false;
    for (Node *n = firstChild(); n; n = n->nextSibling()) {
        bool childRulesChanged = n->changed() && n->styleChangeType() == FullStyleChange;
        if (forceCheckOfNextElementSibling && n->isElementNode())
            n->setChanged();
        if (change >= Inherit || n->isTextNode() || n->hasChangedChild() || n->changed())
            n->recalcStyle(change);
        if (n->isElementNode())
            forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
    }

    setChanged(NoStyleChange);
    setHasChangedChild(false);
}