📄 render_container.cpp
字号:
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); pseudoContainer->close(); }}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. if (!newChild->isFloatingOrPositioned() && childrenInline()) dirtyLinesFromChangedChild(newChild); #if APPLE_CHANGES KWQAccObjectCache* cache = document()->getExistingAccObjectCache(); if (cache) cache->childrenChanged(this);#endif}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. if (!child->isFloatingOrPositioned() && childrenInline()) dirtyLinesFromChangedChild(child); #if APPLE_CHANGES KWQAccObjectCache* cache = document()->getExistingAccObjectCache(); if (cache) cache->childrenChanged(this);#endif }void RenderContainer::layout(){ KHTMLAssert( needsLayout() ); KHTMLAssert( minMaxKnown() ); RenderObject *child = firstChild(); while( child ) { child->layoutIfNeeded(); 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();}Position RenderContainer::positionForCoordinates(int _x, int _y){ // no children...return this render object's element, if there is one, and offset 0 if (!firstChild()) return Position(element(), 0); // look for the geometrically-closest child and pass off to that child int min = INT_MAX; RenderObject *closestRenderer = firstChild(); for (RenderObject *renderer = firstChild(); renderer; renderer = renderer->nextSibling()) { int absx, absy; renderer->absolutePosition(absx, absy); int top = absy + borderTop() + paddingTop(); int bottom = top + renderer->contentHeight(); int left = absx + borderLeft() + paddingLeft(); int right = left + renderer->contentWidth(); int cmp; cmp = abs(_y - top); if (cmp < min) { closestRenderer = renderer; min = cmp; } cmp = abs(_y - bottom); if (cmp < min) { closestRenderer = renderer; min = cmp; } cmp = abs(_x - left); if (cmp < min) { closestRenderer = renderer; min = cmp; } cmp = abs(_x - right); if (cmp < min) { closestRenderer = renderer; min = cmp; } } return closestRenderer->positionForCoordinates(_x, _y);} #undef DEBUG_LAYOUT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -