📄 render_container.cpp
字号:
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; // No generated content if (!oldContentPresent && !newContentWanted) return; // Whether or not we want the same old content. bool sameOldContent = oldContentPresent && newContentWanted && (child->style()->contentDataEquivalent(pseudo)); // No change in content, update style if( sameOldContent ) { child->setStyle(pseudo); return; } // 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 || !sameOldContent)) { // The child needs to be removed. 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); 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. RenderContainer* pseudoContainer = 0; pseudoContainer = RenderFlow::createFlow(element(), pseudo, renderArena()); pseudoContainer->setIsAnonymous( true ); pseudoContainer->createCSSContent(); // Only add the container if it had content if (pseudoContainer->firstChild()) { // 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); pseudoContainer->close(); }}void RenderContainer::createCSSContent(){ RenderStyle* pseudo = style(); RenderStyle* style = new RenderStyle(); style->ref(); style->inheritFrom(pseudo); // 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 (contentData->_contentType == CONTENT_TEXT) { RenderText* t = new (renderArena()) RenderText( node(), 0); t->setIsAnonymous( true ); t->setStyle(style); t->setText(contentData->contentText()); addChild(t); } else if (contentData->_contentType == CONTENT_OBJECT) { RenderImage* img = new (renderArena()) RenderImage(node()); img->setIsAnonymous( true ); img->setStyle(style); img->setContentObject(contentData->contentObject()); addChild(img); } else if (contentData->_contentType == CONTENT_COUNTER) { RenderCounter* t = new (renderArena()) RenderCounter( node(), contentData->contentCounter() ); t->setIsAnonymous( true ); t->setStyle(style); addChild(t); } else if (contentData->_contentType == CONTENT_QUOTE) { RenderQuote* t = new (renderArena()) RenderQuote( node(), contentData->contentQuote() ); t->setIsAnonymous( true ); t->setStyle(style); addChild(t); } } style->deref();}void RenderContainer::appendChildNode(RenderObject* newChild){ KHTMLAssert(newChild->parent() == 0); newChild->setParent(this); RenderObject* lChild = lastChild(); if(lChild) { newChild->setPreviousSibling(lChild); lChild->setNextSibling(newChild); } else setFirstChild(newChild); setLastChild(newChild); // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children // and don't have a layer attached to ourselves. if (newChild->firstChild() || newChild->layer()) { RenderLayer* layer = enclosingLayer(); newChild->addLayers(layer, newChild); } newChild->setNeedsLayoutAndMinMaxRecalc(); // Goes up the containing block hierarchy. if (!normalChildNeedsLayout()) setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.}void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild){ if(!beforeChild) { appendChildNode(child); return; } KHTMLAssert(!child->parent()); while ( beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock() ) beforeChild = beforeChild->parent(); KHTMLAssert(beforeChild->parent() == this); if(beforeChild == firstChild()) setFirstChild(child); RenderObject* prev = beforeChild->previousSibling(); child->setNextSibling(beforeChild); beforeChild->setPreviousSibling(child); if(prev) prev->setNextSibling(child); child->setPreviousSibling(prev); child->setParent(this); // Keep our layer hierarchy updated. RenderLayer* layer = enclosingLayer(); child->addLayers(layer, child); child->setNeedsLayoutAndMinMaxRecalc(); if (!normalChildNeedsLayout()) setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.}void RenderContainer::layout(){ KHTMLAssert( needsLayout() ); KHTMLAssert( minMaxKnown() ); const bool pagedMode = canvas()->pagedMode(); RenderObject *child = firstChild(); while( child ) { if (pagedMode) child->setNeedsLayout(true); child->layoutIfNeeded(); if (child->containsPageBreak()) setContainsPageBreak(true); if (child->needsPageClear()) setNeedsPageClear(true); child = child->nextSibling(); } setNeedsLayout(false);}void RenderContainer::removeLeftoverAnonymousBoxes(){ // we have to go over all child nodes and remove anonymous boxes, that do _not_ // have inline children to keep the tree flat RenderObject *child = firstChild(); while( child ) { RenderObject *next = child->nextSibling(); if ( child->isRenderBlock() && child->isAnonymousBlock() && !child->continuation() && !child->childrenInline() && !child->isTableCell() ) { RenderObject *firstAnChild = child->firstChild(); RenderObject *lastAnChild = child->lastChild(); if ( firstAnChild ) { RenderObject *o = firstAnChild; while( o ) { o->setParent( this ); o = o->nextSibling(); } firstAnChild->setPreviousSibling( child->previousSibling() ); lastAnChild->setNextSibling( child->nextSibling() ); if ( child->previousSibling() ) child->previousSibling()->setNextSibling( firstAnChild ); if ( child->nextSibling() ) child->nextSibling()->setPreviousSibling( lastAnChild ); } else { if ( child->previousSibling() ) child->previousSibling()->setNextSibling( child->nextSibling() ); if ( child->nextSibling() ) child->nextSibling()->setPreviousSibling( child->previousSibling() ); } if ( child == firstChild() ) m_first = firstAnChild; if ( child == lastChild() ) m_last = lastAnChild; child->setParent( 0 ); child->setPreviousSibling( 0 ); child->setNextSibling( 0 ); if ( !child->isText() ) { RenderContainer *c = static_cast<RenderContainer *>(child); c->m_first = 0; c->m_next = 0; } child->detach(); } child = next; } if ( parent() ) parent()->removeLeftoverAnonymousBoxes();}#undef DEBUG_LAYOUT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -