📄 render_block.cpp
字号:
int oldTopNegMargin = m_maxTopNegMargin; if (legend == child) { child = child->nextSibling(); continue; // Skip the legend, since it has already been positioned up in the fieldset's border. } // make sure we relayout children if we need it. if (relayoutChildren || floatBottom() > m_y || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())) || (child->isRenderBlock() && child->style()->height().isPercent())) child->setChildNeedsLayout(true); // kdDebug( 6040 ) << " " << child->renderName() << " loop " << child << ", " << child->isInline() << ", " << child->needsLayout() << endl; // kdDebug( 6040 ) << t.elapsed() << endl; // ### might be some layouts are done two times... FIX that. if (child->isPositioned()) { child->containingBlock()->insertPositionedObject(child); if (child->hasStaticX()) { if (style()->direction() == LTR) child->setStaticX(xPos); else child->setStaticX(borderRight()+paddingRight()); } if (child->hasStaticY()) { int marginOffset = 0; bool shouldSynthesizeCollapse = (!topMarginContributor || !canCollapseTopWithChildren); if (shouldSynthesizeCollapse) { int collapsedTopPos = prevPosMargin; int collapsedTopNeg = prevNegMargin; bool posMargin = child->marginTop() >= 0; if (posMargin && child->marginTop() > collapsedTopPos) collapsedTopPos = child->marginTop(); else if (!posMargin && child->marginTop() > collapsedTopNeg) collapsedTopNeg = child->marginTop(); marginOffset += (collapsedTopPos - collapsedTopNeg) - child->marginTop(); } int yPosEstimate = m_height + marginOffset; child->setStaticY(yPosEstimate); } child = child->nextSibling(); continue; } else if (child->isReplaced()) child->layoutIfNeeded(); if ( child->isFloating() ) { insertFloatingObject( child ); // The float should be positioned taking into account the bottom margin // of the previous flow. We add that margin into the height, get the // float positioned properly, and then subtract the margin out of the // height again. In the case of self-collapsing blocks, we always just // use the top margins, since the self-collapsing block collapsed its // own bottom margin into its top margin. // // Note also that the previous flow may collapse its margin into the top of // our block. If this is the case, then we do not add the margin in to our // height when computing the position of the float. This condition can be tested // for by simply checking the boolean |topMarginContributor| variable. See // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for // an example of this scenario. int marginOffset = (!topMarginContributor || !canCollapseTopWithChildren) ? (prevPosMargin - prevNegMargin) : 0; m_height += marginOffset; positionNewFloats(); m_height -= marginOffset; //kdDebug() << "RenderBlock::layoutBlockChildren inserting float at "<< m_height <<" prevMargin="<<prevMargin << endl; child = child->nextSibling(); continue; } // See if we have a compact element. If we do, then try to tuck the compact // element into the margin space of the next block. // FIXME: We only deal with one compact at a time. It is unclear what should be // done if multiple contiguous compacts are encountered. For now we assume that // compact A followed by another compact B should simply be treated as block A. if (child->isCompact() && !compactChild && (child->childrenInline() || child->isReplaced())) { // Get the next non-positioned/non-floating RenderBlock. RenderObject* next = child->nextSibling(); RenderObject* curr = next; while (curr && curr->isFloatingOrPositioned()) curr = curr->nextSibling(); if (curr && curr->isRenderBlock() && !curr->isCompact() && !curr->isRunIn()) { curr->calcWidth(); // So that horizontal margins are correct. // Need to compute margins for the child as though it is a block. child->style()->setDisplay(BLOCK); child->calcWidth(); child->style()->setDisplay(COMPACT); int childMargins = child->marginLeft() + child->marginRight(); int margin = style()->direction() == LTR ? curr->marginLeft() : curr->marginRight(); if (margin < (childMargins + child->maxWidth())) { // It won't fit. Kill the "compact" boolean and just treat // the child like a normal block. This is only temporary. child->style()->setDisplay(BLOCK); treatCompactAsBlock = true; } else { blockForCompactChild = curr; compactChild = child; child->setInline(true); child->setPos(0,0); // This position will be updated to reflect the compact's // desired position and the line box for the compact will // pick that position up. // Remove the child. RenderObject* next = child->nextSibling(); removeChildNode(child); // Now insert the child under |curr|. curr->insertChildNode(child, curr->firstChild()); child = next; continue; } } } // See if we have a run-in element with inline children. If the // children aren't inline, then just treat the run-in as a normal // block. if (child->isRunIn() && (child->childrenInline() || child->isReplaced())) { // Get the next non-positioned/non-floating RenderBlock. RenderObject* curr = child->nextSibling(); while (curr && curr->isFloatingOrPositioned()) curr = curr->nextSibling(); if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isCompact() && !curr->isRunIn())) { // The block acts like an inline, so just null out its // position. child->setInline(true); child->setPos(0,0); // Remove the child. RenderObject* next = child->nextSibling(); removeChildNode(child); // Now insert the child under |curr|. curr->insertChildNode(child, curr->firstChild()); child = next; continue; } } child->calcVerticalMargins(); // Try to guess our correct y position. In most cases this guess will // be correct. Only if we're wrong (when we compute the real y position) // will we have to relayout. int yPosEstimate = m_height; if (prevBlock) { yPosEstimate += kMax(prevBlock->collapsedMarginBottom(), child->marginTop()); if (prevFlow) { if (prevFlow->yPos() + prevFlow->floatBottom() > yPosEstimate) child->setChildNeedsLayout(true); else prevFlow = 0; } } else if (!canCollapseTopWithChildren || !topMarginContributor) yPosEstimate += child->marginTop(); // Note this occurs after the test for positioning and floating above, sincep // we want to ensure that we don't artificially increase our height because of // a positioned or floating child. int fb = floatBottom(); if (child->avoidsFloats() && style()->width().isFixed() && child->minWidth() > lineWidth(m_height)) { if (fb > m_height) { m_height = yPosEstimate = fb; shouldCollapseChild = false; clearOccurred = true; prevFlow = 0; prevBlock = 0; } } // take care in case we inherited floats if (fb > m_height) child->setChildNeedsLayout(true); //kdDebug(0) << "margin = " << margin << " yPos = " << m_height << endl; int oldChildX = child->xPos(); int oldChildY = child->yPos(); // Go ahead and position the child as though it didn't collapse with the top. child->setPos(child->xPos(), yPosEstimate); child->layoutIfNeeded(); // Now determine the correct ypos based off examination of collapsing margin // values. if (shouldCollapseChild) { // Get our max pos and neg top margins. int posTop = child->maxTopMargin(true); int negTop = child->maxTopMargin(false); // For self-collapsing blocks, collapse our bottom margins into our // top to get new posTop and negTop values. if (child->isSelfCollapsingBlock()) { if (child->maxBottomMargin(true) > posTop) posTop = child->maxBottomMargin(true); if (child->maxBottomMargin(false) > negTop) negTop = child->maxBottomMargin(false); } // See if the top margin is quirky. We only care if this child has // margins that will collapse with us. bool topQuirk = child->isTopMarginQuirk(); if (canCollapseTopWithChildren && topMarginContributor && !clearOccurred) { // This child is collapsing with the top of the // block. If it has larger margin values, then we need to update // our own maximal values. if (strictMode || !quirkContainer || !topQuirk) { if (posTop > m_maxTopPosMargin) m_maxTopPosMargin = posTop; if (negTop > m_maxTopNegMargin) m_maxTopNegMargin = negTop; } // The minute any of the margins involved isn't a quirk, don't // collapse it away, even if the margin is smaller (www.webreference.com // has an example of this, a <dt> with 0.8em author-specified inside // a <dl> inside a <td>. if (!determinedTopQuirk && !topQuirk && (posTop-negTop)) { m_topMarginQuirk = false; determinedTopQuirk = true; } if (!determinedTopQuirk && topQuirk && marginTop() == 0) // We have no top margin and our top child has a quirky margin. // We will pick up this quirky margin and pass it through. // This deals with the <td><div><p> case. // Don't do this for a block that split two inlines though. You do // still apply margins in this case. m_topMarginQuirk = true; } if (quirkContainer && topMarginContributor && (posTop-negTop)) topChildQuirk = topQuirk; int ypos = m_height; if (child->isSelfCollapsingBlock()) { // This child has no height. We need to compute our // position before we collapse the child's margins together, // so that we can get an accurate position for the zero-height block. int collapsedTopPos = prevPosMargin; int collapsedTopNeg = prevNegMargin; if (child->maxTopMargin(true) > prevPosMargin) collapsedTopPos = prevPosMargin = child->maxTopMargin(true); if (child->maxTopMargin(false) > prevNegMargin) collapsedTopNeg = prevNegMargin = child->maxTopMargin(false); // Now collapse the child's margins together, which means examining our // bottom margin values as well. if (child->maxBottomMargin(true) > prevPosMargin) prevPosMargin = child->maxBottomMargin(true); if (child->maxBottomMargin(false) > prevNegMargin) prevNegMargin = child->maxBottomMargin(false); if (!canCollapseTopWithChildren || !topMarginContributor) // We need to make sure that the position of the self-collapsing block // is correct, since it could have overflowing content // that needs to be positioned correctly (e.g., a block that // had a specified height of 0 but that actually had subcontent). ypos = m_height + collapsedTopPos - collapsedTopNeg; } else { if (!topMarginContributor || (!canCollapseTopWithChildren && (strictMode || !quirkContainer || !topChildQuirk) )) { // We're collapsing with a previous sibling's margins and not // with the top of the block. int absPos = prevPosMargin > posTop ? prevPosMargin : posTop; int absNeg = prevNegMargin > negTop ? prevNegMargin : negTop; int collapsedMargin = absPos - absNeg; m_height += collapsedMargin; ypos = m_height; } prevPosMargin = child->maxBottomMargin(true); prevNegMargin = child->maxBottomMargin(false); if (prevPosMargin-prevNegMargin) { bottomChildQuirk = child->isBottomMarginQuirk(); } selfCollapsingBlockClearedFloat = false; } child->setPos(child->xPos(), ypos); if (ypos != yPosEstimate) { if (child->style()->width().isPercent() && child->usesLineWidth()) // The child's width is a percentage of the line width. // When the child shifts to clear an item, its width can // change (because it has more available line width). // So go ahead and mark the item as dirty. child->setChildNeedsLayout(true); if (child->containsFloats() || containsFloats()) child->markAllDescendantsWithFloatsForLayout(); // Our guess was wrong. Make the child lay itself out again. child->layoutIfNeeded(); } } else selfCollapsingBlockClearedFloat = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -