Beispiel #1
0
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Make sure we don't append things after :after-generated content if we have it.
    if (!beforeChild)
        beforeChild = findAfterContentRenderer();

    if (!child->isTableCell()) {
        RenderObject* last = beforeChild;
        if (!last)
            last = lastChild();
        if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
            if (beforeChild == last)
                beforeChild = last->firstChild();
            last->addChild(child, beforeChild);
            return;
        }

        if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
            RenderObject* cell = beforeChild->previousSibling();
            if (cell && cell->isTableCell()) {
                ASSERT(cell->isAnonymous());
                cell->addChild(child);
                return;
            }
        }

        // If beforeChild is inside an anonymous cell, insert into the cell.
        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
            last->parent()->addChild(child, beforeChild);
            return;
        }

        RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
        RefPtr<RenderStyle> newStyle = RenderStyle::create();
        newStyle->inheritFrom(style());
        newStyle->setDisplay(TABLE_CELL);
        cell->setStyle(newStyle.release());
        addChild(cell, beforeChild);
        cell->addChild(child);
        return;
    } 
    
    // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that.
    while (beforeChild && beforeChild->parent() != this)
        beforeChild = beforeChild->parent();

    RenderTableCell* cell = toRenderTableCell(child);

    // Generated content can result in us having a null section so make sure to null check our parent.
    if (parent())
        section()->addCell(cell, this);

    ASSERT(!beforeChild || beforeChild->isTableCell());
    RenderBox::addChild(cell, beforeChild);

    if (beforeChild || nextSibling())
        section()->setNeedsCellRecalc();
}
Beispiel #2
0
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Make sure we don't append things after :after-generated content if we have it.
    if (!beforeChild)
        beforeChild = afterPseudoElementRenderer();

    if (!child->isTableCell()) {
        RenderObject* last = beforeChild;
        if (!last)
            last = lastChild();
        if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
            if (beforeChild == last)
                beforeChild = last->firstChild();
            last->addChild(child, beforeChild);
            return;
        }

        if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
            RenderObject* cell = beforeChild->previousSibling();
            if (cell && cell->isTableCell() && cell->isAnonymous()) {
                cell->addChild(child);
                return;
            }
        }

        // If beforeChild is inside an anonymous cell, insert into the cell.
        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
            last->parent()->addChild(child, beforeChild);
            return;
        }

        RenderTableCell* cell = RenderTableCell::createAnonymousWithParentRenderer(this);
        addChild(cell, beforeChild);
        cell->addChild(child);
        return;
    } 
    
    // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that.
    while (beforeChild && beforeChild->parent() != this)
        beforeChild = beforeChild->parent();

    RenderTableCell* cell = toRenderTableCell(child);

    // Generated content can result in us having a null section so make sure to null check our parent.
    if (parent())
        section()->addCell(cell, this);

    ASSERT(!beforeChild || beforeChild->isTableCell());
    RenderBox::addChild(cell, beforeChild);

    if (beforeChild || nextSibling())
        section()->setNeedsCellRecalc();
}
Beispiel #3
0
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
    if (!child->isTableCell()) {
        RenderObject* last = beforeChild;
        if (!last)
            last = lastChild();
        if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
            if (beforeChild == last)
                beforeChild = last->firstChild();
            last->addChild(child, beforeChild);
            return;
        }

        if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
            RenderObject* cell = beforeChild->previousSibling();
            if (cell && cell->isTableCell() && cell->isAnonymous()) {
                cell->addChild(child);
                return;
            }
        }

        // If beforeChild is inside an anonymous cell, insert into the cell.
        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
            last->parent()->addChild(child, beforeChild);
            return;
        }

        RenderTableCell* cell = RenderTableCell::createAnonymousWithParentRenderer(this);
        addChild(cell, beforeChild);
        cell->addChild(child);
        return;
    } 

    if (beforeChild && beforeChild->parent() != this)
        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);    

    RenderTableCell* cell = toRenderTableCell(child);

    // Generated content can result in us having a null section so make sure to null check our parent.
    if (parent())
        section()->addCell(cell, this);

    ASSERT(!beforeChild || beforeChild->isTableCell());
    RenderBox::addChild(cell, beforeChild);

    if (beforeChild || nextSibling())
        section()->setNeedsCellRecalc();
}
Beispiel #4
0
static void createRendererIfNeeded(Element& element, RenderStyle* resolvedStyle)
{
    ASSERT(!element.renderer());

    Document& document = element.document();
    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&element);

    RefPtr<RenderStyle> style = resolvedStyle;

    element.setIsInsideRegion(false);

    if (!shouldCreateRenderer(element, renderingParentNode) && !elementInsideRegionNeedsRenderer(element, renderingParentNode, style))
        return;

    if (!style)
        style = element.styleForRenderer();

    RenderNamedFlowThread* parentFlowRenderer = 0;
#if ENABLE(CSS_REGIONS)
    parentFlowRenderer = moveToFlowThreadIfNeeded(element, *style);
#endif

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

    RenderObject* parentRenderer;
    RenderObject* nextRenderer;
    if (parentFlowRenderer) {
        parentRenderer = parentFlowRenderer;
        nextRenderer = parentFlowRenderer->nextRendererForNode(&element);
    } else {
        parentRenderer = renderingParentNode->renderer();
        nextRenderer = nextSiblingRenderer(element, renderingParentNode);
    }

    RenderObject* newRenderer = element.createRenderer(document.renderArena(), style.get());
    if (!newRenderer)
        return;
    if (!parentRenderer->isChildAllowed(newRenderer, style.get())) {
        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(parentRenderer->flowThreadState());

    element.setRenderer(newRenderer);
    newRenderer->setAnimatableStyle(style.release()); // setAnimatableStyle() can depend on renderer() already being set.

#if ENABLE(FULLSCREEN_API)
    if (document.webkitIsFullScreen() && document.webkitCurrentFullScreenElement() == &element) {
        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, &document);
        if (!newRenderer)
            return;
    }
#endif
    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    parentRenderer->addChild(newRenderer, nextRenderer);
}
Beispiel #5
0
void RenderListItem::updateMarkerLocation()
{
    // Sanity check the location of our marker.
    if (m_marker) {
        RenderObject* markerPar = m_marker->parent();
        RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
        if (!lineBoxParent) {
            // If the marker is currently contained inside an anonymous box,
            // then we are the only item in that anonymous box (since no line box
            // parent was found).  It's ok to just leave the marker where it is
            // in this case.
            if (markerPar && markerPar->isAnonymousBlock())
                lineBoxParent = markerPar;
            else
                lineBoxParent = this;
        }
        
        if (markerPar != lineBoxParent || !m_marker->minMaxKnown()) {
            m_marker->remove();
            if (!lineBoxParent)
                lineBoxParent = this;
            lineBoxParent->addChild(m_marker, lineBoxParent->firstChild());
            if (!m_marker->minMaxKnown())
                m_marker->calcMinMaxWidth();
            recalcMinMaxWidths();
        }
    }
}
Beispiel #6
0
void RenderTreeBuilder::createRendererForTextIfNeeded()
{
    ASSERT(!m_node->renderer());

    // If we're out of composition then we can't render since there's no parent to inherit from.
    if (!m_renderingParent)
        return;

    if (!shouldCreateRenderer())
        return;

    Text* textNode = toText(m_node);
    RenderObject* parentRenderer = this->parentRenderer();

    m_style = parentRenderer->style();

    if (!textNode->textRendererIsNeeded(*m_style, *parentRenderer))
        return;

    RenderText* newRenderer = textNode->createTextRenderer(m_style.get());
    if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
        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(parentRenderer->flowThreadState());

    RenderObject* nextRenderer = this->nextRenderer();
    textNode->setRenderer(newRenderer);
    // Parent takes care of the animations, no need to call setAnimatableStyle.
    newRenderer->setStyle(m_style.release());
    parentRenderer->addChild(newRenderer, nextRenderer);
}
void RenderListItem::updateMarkerLocation()
{
    // Sanity check the location of our marker.
    if (m_marker) {
        RenderObject* markerPar = m_marker->parent();
        RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
        if (!lineBoxParent) {
            // If the marker is currently contained inside an anonymous box,
            // then we are the only item in that anonymous box (since no line box
            // parent was found).  It's ok to just leave the marker where it is
            // in this case.
            if (markerPar && markerPar->isAnonymousBlock())
                lineBoxParent = markerPar;
            else
                lineBoxParent = this;
        }

        if (markerPar != lineBoxParent || m_marker->preferredLogicalWidthsDirty()) {
            // Removing and adding the marker can trigger repainting in
            // containers other than ourselves, so we need to disable LayoutState.
            view()->disableLayoutState();
            updateFirstLetter();
            m_marker->remove();
            if (!lineBoxParent)
                lineBoxParent = this;
            lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
            if (m_marker->preferredLogicalWidthsDirty())
                m_marker->computePreferredLogicalWidths();
            view()->enableLayoutState();
        }
    }
}
void NodeRenderingContext::createRendererForTextIfNeeded()
{
    ASSERT(!m_node->renderer());

    Text* textNode = toText(m_node);

    if (!shouldCreateRenderer())
        return;

    RenderObject* parentRenderer = this->parentRenderer();

    if (m_parentDetails.resetStyleInheritance())
        m_style = textNode->document()->styleResolver()->defaultStyleForElement();
    else
        m_style = parentRenderer->style();

    if (!textNode->textRendererIsNeeded(*this))
        return;

    RenderText* newRenderer = textNode->createTextRenderer(m_style.get());
    if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
        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(parentRenderer->flowThreadState());

    RenderObject* nextRenderer = this->nextRenderer();
    textNode->setRenderer(newRenderer);
    // Parent takes care of the animations, no need to call setAnimatableStyle.
    newRenderer->setStyle(m_style.release());
    parentRenderer->addChild(newRenderer, nextRenderer);
}
Beispiel #9
0
void PseudoElement::attach(const AttachContext& context)
{
    ASSERT(!renderer());

    Element::attach(context);

    RenderObject* renderer = this->renderer();
    if (!renderer)
        return;
    RenderStyle* style = renderer->style();
    if (style->hasFlowFrom())
        return;
    if (style->styleType() != BEFORE && style->styleType() != AFTER)
        return;
    ASSERT(style->contentData());

    for (const ContentData* content = style->contentData(); content; content = content->next()) {
        RenderObject* child = content->createRenderer(document(), style);
        if (renderer->isChildAllowed(child, style)) {
            renderer->addChild(child);
            if (child->isQuote())
                toRenderQuote(child)->attachQuote();
        } else
            child->destroy();
    }
}
Beispiel #10
0
bool RenderListItem::updateMarkerLocation()
{
    ASSERT(m_marker);
    RenderObject* markerParent = m_marker->parent();
    RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
    if (!lineBoxParent) {
        // If the marker is currently contained inside an anonymous box, then we
        // are the only item in that anonymous box (since no line box parent was
        // found). It's ok to just leave the marker where it is in this case.
        if (markerParent && markerParent->isAnonymousBlock())
            lineBoxParent = markerParent;
        else
            lineBoxParent = this;
    }

    if (markerParent != lineBoxParent) {
        m_marker->remove();
        lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
        m_marker->updateMarginsAndContent();
        // If markerParent is an anonymous block with no children, destroy it.
        if (markerParent && markerParent->isAnonymousBlock() && !toRenderBlock(markerParent)->firstChild() && !toRenderBlock(markerParent)->continuation())
            markerParent->destroy();
        return true;
    }

    return false;
}
Beispiel #11
0
void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild)
{
    ASSERT(child);

    if (child->isRubyText()) {
        if (!beforeChild) {
            // RenderRuby has already ascertained that we can add the child here.
            ASSERT(!hasRubyText());
            // prepend ruby texts as first child
            RenderBlockFlow::addChild(child, firstChild());
        }  else if (beforeChild->isRubyText()) {
            // New text is inserted just before another.
            // In this case the new text takes the place of the old one, and
            // the old text goes into a new run that is inserted as next sibling.
            ASSERT(beforeChild->parent() == this);
            RenderObject* ruby = parent();
            ASSERT(ruby->isRuby());
            RenderBlock* newRun = staticCreateRubyRun(ruby);
            ruby->addChild(newRun, nextSibling());
            // Add the new ruby text and move the old one to the new run
            // Note: Doing it in this order and not using RenderRubyRun's methods,
            // in order to avoid automatic removal of the ruby run in case there is no
            // other child besides the old ruby text.
            RenderBlockFlow::addChild(child, beforeChild);
            RenderBlockFlow::removeChild(beforeChild);
            newRun->addChild(beforeChild);
        } else if (hasRubyBase()) {
            // Insertion before a ruby base object.
            // In this case we need insert a new run before the current one and split the base.
            RenderObject* ruby = parent();
            RenderRubyRun* newRun = staticCreateRubyRun(ruby);
            ruby->addChild(newRun, this);
            newRun->addChild(child);
            rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild);
        }
    } else {
        // child is not a text -> insert it into the base
        // (append it instead if beforeChild is the ruby text)
        RenderRubyBase* base = rubyBaseSafe();
        if (beforeChild == base)
            beforeChild = base->firstChild();
        if (beforeChild && beforeChild->isRubyText())
            beforeChild = 0;
        ASSERT(!beforeChild || beforeChild->isDescendantOf(base));
        base->addChild(child, beforeChild);
    }
}
Beispiel #12
0
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Make sure we don't append things after :after-generated content if we have it.
    if (!beforeChild && isAfterContent(lastChild()))
        beforeChild = lastChild();

    bool isTableRow = element() && element()->hasTagName(trTag);

#if ENABLE(WML)
    if (!isTableRow && element() && element()->isWMLElement())
        isTableRow = element()->hasTagName(WMLNames::trTag);
#endif

    if (!child->isTableCell()) {
        if (isTableRow && child->element() && child->element()->hasTagName(formTag) && document()->isHTMLDocument()) {
            RenderContainer::addChild(child, beforeChild);
            return;
        }

        RenderObject* last = beforeChild;
        if (!last)
            last = lastChild();
        if (last && last->isAnonymous() && last->isTableCell()) {
            last->addChild(child);
            return;
        }

        // If beforeChild is inside an anonymous cell, insert into the cell.
        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) {
            last->parent()->addChild(child, beforeChild);
            return;
        }

        RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
        RefPtr<RenderStyle> newStyle = RenderStyle::create();
        newStyle->inheritFrom(style());
        newStyle->setDisplay(TABLE_CELL);
        cell->setStyle(newStyle.release());
        addChild(cell, beforeChild);
        cell->addChild(child);
        return;
    }

    // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that.
    while (beforeChild && beforeChild->parent() != this)
        beforeChild = beforeChild->parent();

    RenderTableCell* cell = static_cast<RenderTableCell*>(child);

    // Generated content can result in us having a null section so make sure to null check our parent.
    if (parent())
        section()->addCell(cell, this);

    ASSERT(!beforeChild || beforeChild->isTableCell() || isTableRow && beforeChild->element() && beforeChild->element()->hasTagName(formTag) && document()->isHTMLDocument());
    RenderContainer::addChild(cell, beforeChild);

    if (beforeChild || nextSibling())
        section()->setNeedsCellRecalc();
}
void TextImpl::attach(KHTMLView *w)
{
    RenderObject *r = _parent->renderer();
    if(r && style())
    {
	m_render = new RenderText(str);
	m_render->setStyle(style());
	r->addChild(m_render, _next ? _next->renderer() : 0);
    }
    CharacterDataImpl::attach(w);
}
Beispiel #14
0
void NodeRenderingContext::createRendererForElementIfNeeded()
{
    ASSERT(!m_node->renderer());

    Element* element = toElement(m_node);

    if (!shouldCreateRenderer())
        return;
    m_style = element->styleForRenderer();
    ASSERT(m_style);

    moveToFlowThreadIfNeeded();

    if (!element->rendererIsNeeded(*this))
        return;

    RenderObject* parentRenderer = this->parentRenderer();
    RenderObject* nextRenderer = this->nextRenderer();
    
#if ENABLE(DIALOG_ELEMENT)
    if (element->isInTopLayer())
        adjustInsertionPointForTopLayerElement(element, parentRenderer, nextRenderer);
#endif

    Document* document = element->document();
    RenderObject* newRenderer = element->createRenderer(document->renderArena(), m_style.get());
    if (!newRenderer)
        return;
    if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
        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->setInRenderFlowThread(parentRenderer->inRenderFlowThread());

    element->setRenderer(newRenderer);
    newRenderer->setAnimatableStyle(m_style.release()); // setAnimatableStyle() can depend on renderer() already being set.

#if ENABLE(FULLSCREEN_API)
    if (document->webkitIsFullScreen() && document->webkitCurrentFullScreenElement() == element) {
        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, document);
        if (!newRenderer)
            return;
    }
#endif
    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    parentRenderer->addChild(newRenderer, nextRenderer);
}
void NodeRenderingContext::createRendererForElementIfNeeded()
{
    ASSERT(!m_node->renderer());

    Element* element = toElement(m_node);

    element->setIsInsideRegion(false);

    if (!shouldCreateRenderer() && !elementInsideRegionNeedsRenderer())
        return;

    if (!m_style)
        m_style = element->styleForRenderer();
    ASSERT(m_style);

    moveToFlowThreadIfNeeded();

    if (!element->rendererIsNeeded(*this))
        return;

    RenderObject* newRenderer = element->createRenderer(m_style.get());
    if (!newRenderer)
        return;

    RenderObject* parentRenderer = this->parentRenderer();

    if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
        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(parentRenderer->flowThreadState());

    RenderObject* nextRenderer = this->nextRenderer();
    element->setRenderer(newRenderer);
    newRenderer->setAnimatableStyle(m_style.release()); // setAnimatableStyle() can depend on renderer() already being set.

    if (FullscreenElementStack::isActiveFullScreenElement(element)) {
        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, element->document());
        if (!newRenderer)
            return;
    }

    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    parentRenderer->addChild(newRenderer, nextRenderer);
}
void HTMLTextFormControlElement::fixPlaceholderRenderer(HTMLElement* placeholder, HTMLElement* siblingElement)
{
    // FIXME: We should change the order of DOM nodes. But it makes an assertion
    // failure in editing code.
    if (!placeholder || !placeholder->renderer())
        return;
    RenderObject* placeholderRenderer = placeholder->renderer();
    RenderObject* siblingRenderer = siblingElement->renderer();
    ASSERT(siblingRenderer);
    if (placeholderRenderer->nextSibling() == siblingRenderer)
        return;
    RenderObject* parentRenderer = placeholderRenderer->parent();
    ASSERT(parentRenderer == siblingRenderer->parent());
    parentRenderer->removeChild(placeholderRenderer);
    parentRenderer->addChild(placeholderRenderer, siblingRenderer);
}
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
    bool isTableRow = element() && element()->hasTagName(trTag);
    
    if (!child->isTableCell()) {
        if (isTableRow && child->element() && child->element()->hasTagName(formTag) && document()->isHTMLDocument()) {
            RenderContainer::addChild(child, beforeChild);
            return;
        }

        RenderObject* last = beforeChild;
        if (!last)
            last = lastChild();
        if (last && last->isAnonymous() && last->isTableCell()) {
            last->addChild(child);
            return;
        }

        // If beforeChild is inside an anonymous cell, insert into the cell.
        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) {
            last->parent()->addChild(child, beforeChild);
            return;
        }

        RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
        RenderStyle* newStyle = new (renderArena()) RenderStyle();
        newStyle->inheritFrom(style());
        newStyle->setDisplay(TABLE_CELL);
        cell->setStyle(newStyle);
        addChild(cell, beforeChild);
        cell->addChild(child);
        return;
    } 
    
    // If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that.
    while (beforeChild && !beforeChild->isTableCell())
        beforeChild = beforeChild->parent();

    RenderTableCell* cell = static_cast<RenderTableCell*>(child);

    section()->addCell(cell, this);

    RenderContainer::addChild(cell, beforeChild);

    if (beforeChild || nextSibling())
        section()->setNeedsCellRecalc();
}
Beispiel #18
0
void NodeRenderingContext::createRendererIfNeeded()
{
    ASSERT(!m_node->renderer());

    if (!shouldCreateRenderer())
        return;
    Element* element = m_node->isElementNode() ? toElement(m_node) : 0;
    
    m_style = element ? element->styleForRenderer() : parentRenderer()->style();
    ASSERT(m_style);

    moveToFlowThreadIfNeeded();

    if (!m_node->rendererIsNeeded(*this)) {
        if (element && m_style->affectedByEmpty())
            element->setStyleAffectedByEmpty();
        return;
    }
    RenderObject* parentRenderer = this->parentRenderer();
    RenderObject* nextRenderer = this->nextRenderer();

#if ENABLE(DIALOG_ELEMENT)
    if (element && element->isInTopLayer())
        adjustInsertionPointForTopLayerElement(element, parentRenderer, nextRenderer);
#endif

    Document* document = m_node->document();
    RenderObject* newRenderer = m_node->createRenderer(document->renderArena(), m_style.get());
    if (!newRenderer)
        return;
    if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
        newRenderer->destroy();
        return;
    }
    m_node->setRenderer(newRenderer);
    newRenderer->setAnimatableStyle(m_style.release()); // setAnimatableStyle() can depend on renderer() already being set.

#if ENABLE(FULLSCREEN_API)
    if (document->webkitIsFullScreen() && document->webkitCurrentFullScreenElement() == m_node) {
        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, document);
        if (!newRenderer)
            return;
    }
#endif
    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    parentRenderer->addChild(newRenderer, nextRenderer);
}
Beispiel #19
0
void RenderTreeBuilder::createRendererForElementIfNeeded()
{
    ASSERT(!m_node->renderer());

    // If we're out of composition then we can't render since there's no parent to inherit from.
    if (!m_renderingParent)
        return;

    Element* element = toElement(m_node);

    if (!shouldCreateRenderer())
        return;

    RenderStyle& style = this->style();

    if (!element->rendererIsNeeded(style))
        return;

    RenderObject* newRenderer = element->createRenderer(&style);
    if (!newRenderer)
        return;

    RenderObject* parentRenderer = this->parentRenderer();

    if (!parentRenderer->isChildAllowed(newRenderer, &style)) {
        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(parentRenderer->flowThreadState());

    RenderObject* nextRenderer = this->nextRenderer();
    element->setRenderer(newRenderer);
    newRenderer->setStyle(&style); // setStyle() can depend on renderer() already being set.

    if (FullscreenElementStack::isActiveFullScreenElement(element)) {
        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, &element->document());
        if (!newRenderer)
            return;
    }

    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    parentRenderer->addChild(newRenderer, nextRenderer);
}
Beispiel #20
0
static void createTextRendererIfNeeded(Text& textNode)
{
    ASSERT(!textNode.renderer());

    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
    if (!renderingParentNode)
        return;
    RenderObject* parentRenderer = renderingParentNode->renderer();
    if (!parentRenderer || !parentRenderer->canHaveChildren())
        return;
    if (!renderingParentNode->childShouldCreateRenderer(&textNode))
        return;

    Document& document = textNode.document();
    RefPtr<RenderStyle> style;
    bool resetStyleInheritance = textNode.parentNode()->isShadowRoot() && toShadowRoot(textNode.parentNode())->resetStyleInheritance();
    if (resetStyleInheritance)
        style = document.ensureStyleResolver().defaultStyleForElement();
    else
        style = parentRenderer->style();

    if (!textRendererIsNeeded(textNode, *parentRenderer, *style))
        return;
    RenderText* newRenderer = textNode.createTextRenderer(document.renderArena(), style.get());
    if (!newRenderer)
        return;
    if (!parentRenderer->isChildAllowed(newRenderer, style.get())) {
        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(parentRenderer->flowThreadState());

    RenderObject* nextRenderer = nextSiblingRenderer(textNode);
    textNode.setRenderer(newRenderer);
    // Parent takes care of the animations, no need to call setAnimatableStyle.
    newRenderer->setStyle(style.release());
    parentRenderer->addChild(newRenderer, nextRenderer);

    Node* sibling = textNode.nextSibling();
    if (sibling && !sibling->renderer() && sibling->attached())
        createTextRenderersForSiblingsAfterAttachIfNeeded(sibling);
}
void NodeRendererFactory::createRendererIfNeeded()
{
    Node* node = m_context.node();
    Document* document = node->document();
    if (!document->shouldCreateRenderers())
        return;

    ASSERT(!node->renderer());
    ASSERT(document->shouldCreateRenderers());

    // FIXME: This side effect should be visible from attach() code.
    m_context.hostChildrenChanged();

    if (!m_context.shouldCreateRenderer())
        return;

    Element* element = node->isElementNode() ? toElement(node) : 0;
    if (element)
        m_context.setStyle(element->styleForRenderer());
    else if (RenderObject* parentRenderer = m_context.parentRenderer())
        m_context.setStyle(parentRenderer->style());

    if (!node->rendererIsNeeded(m_context)) {
        if (element && m_context.style()->affectedByEmpty())
            element->setStyleAffectedByEmpty();
        return;
    }

    RenderObject* parentRenderer = m_context.hasFlowThreadParent() ? m_context.parentFlowRenderer() : m_context.parentRenderer();
    // Do not call m_context.nextRenderer() here in the first clause, because it expects to have
    // the renderer added to its parent already.
    RenderObject* nextRenderer = m_context.hasFlowThreadParent() ? m_context.parentFlowRenderer()->nextRendererForNode(node) : m_context.nextRenderer();
    RenderObject* newRenderer = createRenderer();

#if ENABLE(FULLSCREEN_API)
    if (document->webkitIsFullScreen() && document->webkitCurrentFullScreenElement() == node)
        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, document);
#endif

    if (!newRenderer)
        return;

    // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    parentRenderer->addChild(newRenderer, nextRenderer);
}
Beispiel #22
0
void PseudoElement::didAttachRenderers()
{
    RenderObject* renderer = this->renderer();
    if (!renderer || !renderer->style()->regionThread().isEmpty())
        return;

    RenderStyle* style = renderer->style();
    ASSERT(style->contentData());

    for (const ContentData* content = style->contentData(); content; content = content->next()) {
        RenderObject* child = content->createRenderer(document(), style);
        if (renderer->isChildAllowed(child, style)) {
            renderer->addChild(child);
            if (child->isQuote())
                toRenderQuote(child)->attachQuote();
        } else
            child->destroy();
    }
}
void RenderListItem::updateMarkerLocation()
{
    // Sanity check the location of our marker.
    if (m_marker) {
        RenderObject* markerParent = m_marker->parent();
        RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
        if (!lineBoxParent) {
            // If the marker is currently contained inside an anonymous box,
            // then we are the only item in that anonymous box (since no line box
            // parent was found).  It's ok to just leave the marker where it is
            // in this case.
            if (markerParent && markerParent->isAnonymousBlock())
                lineBoxParent = markerParent;
            else
                lineBoxParent = this;
        }

        if (markerParent != lineBoxParent || m_marker->preferredLogicalWidthsDirty()) {
            // Removing and adding the marker can trigger repainting in
            // containers other than ourselves, so we need to disable LayoutState.
            LayoutStateDisabler layoutStateDisabler(view());
            updateFirstLetter();
            m_marker->remove();
            if (markerParent)
                markerParent->dirtyLinesFromChangedChild(m_marker);
            if (!lineBoxParent)
                lineBoxParent = this;
            lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
            m_marker->updateMarginsAndContent();
            // If markerParent is an anonymous block that has lost all its children, destroy it.
            if (markerParent && markerParent->isAnonymousBlock() && !markerParent->firstChild() && !toRenderBlock(markerParent)->continuation())
                markerParent->destroy();

            // If the marker is inside we need to redo the preferred width calculations
            // as the size of the item now includes the size of the list marker.
            if (m_marker->isInside())
                containingBlock()->updateLogicalWidth();
        }
    }
}
Beispiel #24
0
void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Insert :before and :after content outside of ruby runs.
    if (child->isBeforeContent() || child->isAfterContent()) {
        RenderInline::addChild(child, beforeChild);
        return;
    }

    // If the child is a ruby run, just add it normally.
    if (child->isRubyRun()) {
        RenderInline::addChild(child, beforeChild);
        return;
    }

    if (beforeChild && !isAfterContent(beforeChild)) {
        // insert child into run
        ASSERT(!beforeChild->isRubyRun());
        RenderObject* run = beforeChild;
        while (run && !run->isRubyRun())
            run = run->parent();
        if (run) {
            run->addChild(child, beforeChild);
            return;
        }
        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
        // Emergency fallback: fall through and just append.
    }

    // If the new child would be appended, try to add the child to the previous run
    // if possible, or create a new run otherwise.
    // (The RenderRubyRun object will handle the details)
    RenderRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = RenderRubyRun::staticCreateRubyRun(this);
        RenderInline::addChild(lastRun);
    }
    lastRun->addChild(child);
}
void RenderContainer::updatePseudoChild(RenderStyle::PseudoId type, RenderObject* child)
{
    // In CSS2, before/after pseudo-content cannot nest.  Check this first.
    if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
        return;
    
    RenderStyle* pseudo = getPseudoStyle(type);

    // Whether or not we currently have generated content attached.
    bool oldContentPresent = child && (child->style()->styleType() == type);

    // Whether or not we now want generated content.  
    bool newContentWanted = pseudo && pseudo->display() != NONE;

    // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
    // :after content and not :before content.
    if (type == RenderStyle::BEFORE && isInlineContinuation())
        newContentWanted = false;

    // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
    // then we don't generate the :after content.
    if (type == RenderStyle::AFTER && isRenderInline() && continuation())
        newContentWanted = false;
    
    // If we don't want generated content any longer, or if we have generated content, but it's no longer
    // identical to the new content data we want to build render objects for, then we nuke all
    // of the old generated content.
    if (!newContentWanted ||
        (oldContentPresent && !child->style()->contentDataEquivalent(pseudo))) {
        // Nuke the child. 
        if (child && child->style()->styleType() == type) {
            oldContentPresent = false;
            removeChild(child);
            child = (type == RenderStyle::BEFORE) ? firstChild() : lastChild();
        }
    }

    // If we have no pseudo-style or if the pseudo's display type is NONE, then we
    // have no generated content and can now return.
    if (!newContentWanted)
        return;

    if (isInlineFlow() && pseudo->display() != INLINE)
        // According to the CSS2 spec (the end of section 12.1), the only allowed
        // display values for the pseudo style are NONE and INLINE.  Since we already
        // determined that the pseudo is not display NONE, any display other than
        // inline should be mutated to INLINE.
        pseudo->setDisplay(INLINE);
    
    if (oldContentPresent) {
        if (child && child->style()->styleType() == type) {
            // We have generated content present still.  We want to walk this content and update our
            // style information with the new pseudo style.
            child->setStyle(pseudo);

            // Note that if we ever support additional types of generated content (which should be way off
            // in the future), this code will need to be patched.
            for (RenderObject* genChild = child->firstChild(); genChild; genChild = genChild->nextSibling()) {
                if (genChild->isText())
                    // Generated text content is a child whose style also needs to be set to the pseudo
                    // style.
                    genChild->setStyle(pseudo);
                else {
                    // Images get an empty style that inherits from the pseudo.
                    RenderStyle* style = new (renderArena()) RenderStyle();
                    style->inheritFrom(pseudo);
                    genChild->setStyle(style);
                }
            }
        }
        return; // We've updated the generated content. That's all we needed to do.
    }
    
    RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? child : 0;

    // Generated content consists of a single container that houses multiple children (specified
    // by the content property).  This pseudo container gets the pseudo style set on it.
    RenderObject* pseudoContainer = 0;
    
    // Now walk our list of generated content and create render objects for every type
    // we encounter.
    for (ContentData* contentData = pseudo->contentData();
         contentData; contentData = contentData->_nextContent) {
        if (!pseudoContainer)
            pseudoContainer = RenderFlow::createAnonymousFlow(document(), pseudo); /* anonymous box */
        
        if (contentData->contentType() == CONTENT_TEXT)
        {
            RenderText* t = new (renderArena()) RenderTextFragment(document() /*anonymous object */, contentData->contentText());
            t->setStyle(pseudo);
            pseudoContainer->addChild(t);
        }
        else if (contentData->contentType() == CONTENT_OBJECT)
        {
            RenderImage* img = new (renderArena()) RenderImage(document()); /* Anonymous object */
            RenderStyle* style = new (renderArena()) RenderStyle();
            style->inheritFrom(pseudo);
            img->setStyle(style);
            img->setContentObject(contentData->contentObject());
            pseudoContainer->addChild(img);
        }
    }

    if (pseudoContainer) {
        // Add the pseudo after we've installed all our content, so that addChild will be able to find the text
        // inside the inline for e.g., first-letter styling.
        addChild(pseudoContainer, insertBefore);
    }
}
Beispiel #26
0
void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject)
{
    // Double check that the document did in fact use generated content rules.  Otherwise we should not have been called.
    ASSERT(owner->document()->usesBeforeAfterRules());

    // In CSS2, before/after pseudo-content cannot nest.  Check this first.
    if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER)
        return;
    
    if (!styledObject)
        styledObject = owner;

    RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
    RenderObject* child;
    switch (type) {
    case BEFORE:
        child = beforePseudoElementRenderer(owner);
        break;
    case AFTER:
        child = afterPseudoElementRenderer(owner);
        break;
    default:
        ASSERT_NOT_REACHED();
        return;
    }

    // Whether or not we currently have generated content attached.
    bool oldContentPresent = child;

    // Whether or not we now want generated content.
    bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;

    // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
    // :after content and not :before content.
    if (newContentWanted && type == BEFORE && owner->isElementContinuation())
        newContentWanted = false;

    // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
    // then we don't generate the :after content.
    if (newContentWanted && type == AFTER && owner->virtualContinuation())
        newContentWanted = false;
    
    // If we don't want generated content any longer, or if we have generated content, but it's no longer
    // identical to the new content data we want to build render objects for, then we nuke all
    // of the old generated content.
    if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle, owner->document()) == Node::Detach)) {
        // Nuke the child. 
        if (child->style()->styleType() == type) {
            oldContentPresent = false;
            child->destroy();
            child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild();
        }
    }

    // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
    // have no generated content and can now return.
    if (!newContentWanted)
        return;

    if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && !pseudoElementStyle->isFloating() &&
        !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
        // According to the CSS2 spec (the end of section 12.1), the only allowed
        // display values for the pseudo style are NONE and INLINE for inline flows.
        // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
        // For now we at least relax the restriction to allow all inline types like inline-block
        // and inline-table.
        pseudoElementStyle->setDisplay(INLINE);

    if (oldContentPresent) {
        updateBeforeAfterStyle(child, type, pseudoElementStyle);
        return; // We've updated the generated content. That's all we needed to do.
    }
    
    RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0;
    if (insertBefore && insertBefore->isAnonymousBlock() && insertBefore->childrenInline() && !insertBefore->isEmpty()) {
        // We are going to add the "before" element. We have to check whether the "insertBefore" element
        // is an anonymous block with inline children. If it is, then we should insert the "before" element
        // before the first inline child of the anonymous block, otherwise we will end up with the "before"
        // element in a different block. We do this only when the anonymous block has children, otherwise
        // we end up with the before element in a wrong block.
        insertBefore = insertBefore->firstChild();
    }

    // Nothing goes before the intruded run-in, not even generated content.
    if (insertBefore && insertBefore->isRunIn() && owner->isRenderBlock()
        && toRenderBlock(owner)->runInIsPlacedIntoSiblingBlock(insertBefore))
        insertBefore = insertBefore->nextSibling();

    // Generated content consists of a single container that houses multiple children (specified
    // by the content property).  This generated content container gets the pseudo-element style set on it.
    RenderObject* generatedContentContainer = 0;

    // Walk our list of generated content and create render objects for each.
    for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
        RenderObject* renderer =  createRendererForBeforeAfterContent(owner, content, pseudoElementStyle);

        if (renderer) {
            if (!generatedContentContainer) {
                // Make a generated box that might be any display type now that we are able to drill down into children
                // to find the original content properly.
                generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
                ASSERT(styledObject->node()); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.
                generatedContentContainer->setNode(styledObject->node()); // This allows access to the generatingNode.
                generatedContentContainer->setStyle(pseudoElementStyle);
                if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) {
                    // The generated content container is not allowed here -> abort.
                    generatedContentContainer->destroy();
                    renderer->destroy();
                    return;
                }

                // When we don't have a first child and are part of a continuation chain,
                // insertBefore is incorrectly set to zero above, which causes the :before
                // child to end up at the end of continuation chain.
                // See https://bugs.webkit.org/show_bug.cgi?id=78380.
                if (!insertBefore && type == BEFORE && owner->virtualContinuation())
                    owner->addChildIgnoringContinuation(generatedContentContainer, 0);
                else
                    owner->addChild(generatedContentContainer, insertBefore);
            }
            if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))
                generatedContentContainer->addChild(renderer);
            else
                renderer->destroy();
        }
    }

    if (!generatedContentContainer)
        return;

    // Handle placement of run-ins. We do the run-in placement at the end since generatedContentContainer can get destroyed.
    RenderObject* generatedContentContainerImmediateParent = generatedContentContainer->parent();
    if (generatedContentContainerImmediateParent->isRenderBlock())
        toRenderBlock(generatedContentContainerImmediateParent)->placeRunInIfNeeded(generatedContentContainer, PlaceGeneratedRunIn);
}
Beispiel #27
0
void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Insert :before and :after content before/after the RenderRubyRun(s)
    if (child->isBeforeContent()) {
        if (child->isInline()) {
            // Add generated inline content normally
            RenderBlock::addChild(child, firstChild());
        } else {
            // Wrap non-inline content with an anonymous inline-block.
            RenderBlock* beforeBlock = rubyBeforeBlock(this);
            if (!beforeBlock) {
                beforeBlock = createAnonymousRubyInlineBlock(this);
                RenderBlock::addChild(beforeBlock, firstChild());
            }
            beforeBlock->addChild(child);
        }
        return;
    }
    if (child->isAfterContent()) {
        if (child->isInline()) {
            // Add generated inline content normally
            RenderBlock::addChild(child);
        } else {
            // Wrap non-inline content with an anonymous inline-block.
            RenderBlock* afterBlock = rubyAfterBlock(this);
            if (!afterBlock) {
                afterBlock = createAnonymousRubyInlineBlock(this);
                RenderBlock::addChild(afterBlock);
            }
            afterBlock->addChild(child);
        }
        return;
    }

    // If the child is a ruby run, just add it normally.
    if (child->isRubyRun()) {
        RenderBlock::addChild(child, beforeChild);
        return;
    }

    if (beforeChild && !isAfterContent(beforeChild)) {
        // insert child into run
        ASSERT(!beforeChild->isRubyRun());
        RenderObject* run = beforeChild;
        while (run && !run->isRubyRun())
            run = run->parent();
        if (run) {
            run->addChild(child, beforeChild);
            return;
        }
        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
        // Emergency fallback: fall through and just append.
    }

    // If the new child would be appended, try to add the child to the previous run
    // if possible, or create a new run otherwise.
    // (The RenderRubyRun object will handle the details)
    RenderRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = RenderRubyRun::staticCreateRubyRun(this);
        RenderBlock::addChild(lastRun, beforeChild);
    }
    lastRun->addChild(child);
}
Beispiel #28
0
void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, RenderObject* styledObject)
{
    // Double check that the document did in fact use generated content rules.  Otherwise we should not have been called.
    ASSERT(owner->document()->usesBeforeAfterRules());

    // In CSS2, before/after pseudo-content cannot nest.  Check this first.
    if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER)
        return;
    
    if (!styledObject)
        styledObject = owner;

    RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
    RenderObject* child = beforeAfterContainer(owner, type);

    // Whether or not we currently have generated content attached.
    bool oldContentPresent = child;

    // Whether or not we now want generated content.
    bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;

    // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
    // :after content and not :before content.
    if (newContentWanted && type == BEFORE && owner->isElementContinuation())
        newContentWanted = false;

    // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
    // then we don't generate the :after content.
    if (newContentWanted && type == AFTER && owner->virtualContinuation())
        newContentWanted = false;
    
    // If we don't want generated content any longer, or if we have generated content, but it's no longer
    // identical to the new content data we want to build render objects for, then we nuke all
    // of the old generated content.
    if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) {
        // Nuke the child. 
        if (child->style()->styleType() == type) {
            oldContentPresent = false;
            child->destroy();
            child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild();
        }
    }

    // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
    // have no generated content and can now return.
    if (!newContentWanted)
        return;

    if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
        !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
        // According to the CSS2 spec (the end of section 12.1), the only allowed
        // display values for the pseudo style are NONE and INLINE for inline flows.
        // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
        // For now we at least relax the restriction to allow all inline types like inline-block
        // and inline-table.
        pseudoElementStyle->setDisplay(INLINE);

    if (oldContentPresent) {
        if (child && child->style()->styleType() == type) {
            // We have generated content present still.  We want to walk this content and update our
            // style information with the new pseudo-element style.
            child->setStyle(pseudoElementStyle);

            RenderObject* beforeAfterParent = findBeforeAfterParent(child);
            if (!beforeAfterParent)
                return;

            // Note that if we ever support additional types of generated content (which should be way off
            // in the future), this code will need to be patched.
            for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
                if (genChild->isText())
                    // Generated text content is a child whose style also needs to be set to the pseudo-element style.
                    genChild->setStyle(pseudoElementStyle);
                else if (genChild->isImage()) {
                    // Images get an empty style that inherits from the pseudo.
                    RefPtr<RenderStyle> style = RenderStyle::create();
                    style->inheritFrom(pseudoElementStyle);
                    genChild->setStyle(style.release());
                } else {
                    // RenderListItem may insert a list marker here. We do not need to care about this case.
                    // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it.
                    ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER);
                }
            }
        }
        return; // We've updated the generated content. That's all we needed to do.
    }
    
    RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0;

    // Generated content consists of a single container that houses multiple children (specified
    // by the content property).  This generated content container gets the pseudo-element style set on it.
    RenderObject* generatedContentContainer = 0;
    
    // Walk our list of generated content and create render objects for each.
    for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
        RenderObject* renderer = 0;
        switch (content->type()) {
            case CONTENT_NONE:
                break;
            case CONTENT_TEXT:
                renderer = new (owner->renderArena()) RenderTextFragment(owner->document() /* anonymous object */, content->text());
                renderer->setStyle(pseudoElementStyle);
                break;
            case CONTENT_OBJECT: {
                RenderImageGeneratedContent* image = new (owner->renderArena()) RenderImageGeneratedContent(owner->document()); // anonymous object
                RefPtr<RenderStyle> style = RenderStyle::create();
                style->inheritFrom(pseudoElementStyle);
                image->setStyle(style.release());
                if (StyleImage* styleImage = content->image())
                    image->setStyleImage(styleImage);
                renderer = image;
                break;
            }
            case CONTENT_COUNTER:
                renderer = new (owner->renderArena()) RenderCounter(owner->document(), *content->counter());
                renderer->setStyle(pseudoElementStyle);
                break;
        }

        if (renderer) {
            if (!generatedContentContainer) {
                // Make a generated box that might be any display type now that we are able to drill down into children
                // to find the original content properly.
                generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
                generatedContentContainer->setStyle(pseudoElementStyle);
                owner->addChild(generatedContentContainer, insertBefore);
            }
            generatedContentContainer->addChild(renderer);
        }
    }
}