📄 renderblock.cpp
字号:
// // 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 calling canCollapseWithTop. See // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for // an example of this scenario. int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin(); setHeight(height() + marginOffset); positionNewFloats(); setHeight(height() - marginOffset);}RenderBox* RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginInfo, bool& handled){ // Handle positioned children first. RenderBox* next = handlePositionedChild(child, marginInfo, handled); if (handled) return next; // Handle floating children next. next = handleFloatingChild(child, marginInfo, handled); if (handled) return next; // Finally, see if we have a run-in element. return handleRunInChild(child, handled);}RenderBox* RenderBlock::handlePositionedChild(RenderBox* child, const MarginInfo& marginInfo, bool& handled){ if (child->isPositioned()) { handled = true; child->containingBlock()->insertPositionedObject(child); adjustPositionedBlock(child, marginInfo); return child->nextSiblingBox(); } return 0;}RenderBox* RenderBlock::handleFloatingChild(RenderBox* child, const MarginInfo& marginInfo, bool& handled){ if (child->isFloating()) { handled = true; insertFloatingObject(child); adjustFloatingBlock(marginInfo); return child->nextSiblingBox(); } return 0;}RenderBox* RenderBlock::handleRunInChild(RenderBox* child, bool& handled){ // 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())) { RenderBlock* blockRunIn = toRenderBlock(child); // Get the next non-positioned/non-floating RenderBlock. RenderObject* curr = blockRunIn->nextSibling(); while (curr && curr->isFloatingOrPositioned()) curr = curr->nextSibling(); if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isRunIn())) { RenderBlock* currBlock = toRenderBlock(curr); // The block acts like an inline, so just null out its // position. handled = true; // Remove the old child. RenderBox* next = blockRunIn->nextSiblingBox(); children()->removeChildNode(this, blockRunIn); // Create an inline. RenderInline* inlineRunIn = new (renderArena()) RenderInline(blockRunIn->node()); inlineRunIn->setStyle(blockRunIn->style()); // Move the nodes from the old child to the new child, but skip any :before/:after content. It has already // been regenerated by the new inline. for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild; runInChild = runInChild->nextSibling()) { if (runInChild->style()->styleType() != BEFORE && runInChild->style()->styleType() != AFTER) { blockRunIn->children()->removeChildNode(blockRunIn, runInChild, false); inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content. } } // Now insert the new child under |currBlock|. currBlock->children()->insertChildNode(currBlock, inlineRunIn, currBlock->firstChild()); // If the run-in had an element, we need to set the new renderer. if (blockRunIn->node()) blockRunIn->node()->setRenderer(inlineRunIn); // Destroy the block run-in. blockRunIn->destroy(); return next; } } return 0;}int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo){ // 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()) { posTop = max(posTop, child->maxBottomMargin(true)); negTop = max(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() || style()->marginTopCollapse() == MDISCARD; if (marginInfo.canCollapseWithTop()) { // 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 (!style()->htmlHacks() || !marginInfo.quirkContainer() || !topQuirk) setMaxTopMargins(max(posTop, maxTopPosMargin()), max(negTop, maxTopNegMargin())); // 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 (!marginInfo.determinedTopQuirk() && !topQuirk && (posTop-negTop)) { setTopMarginQuirk(false); marginInfo.setDeterminedTopQuirk(true); } if (!marginInfo.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. setTopMarginQuirk(true); } if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop)) marginInfo.setTopQuirk(topQuirk); int ypos = 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 = max(marginInfo.posMargin(), child->maxTopMargin(true)); int collapsedTopNeg = max(marginInfo.negMargin(), child->maxTopMargin(false)); marginInfo.setMargin(collapsedTopPos, collapsedTopNeg); // Now collapse the child's margins together, which means examining our // bottom margin values as well. marginInfo.setPosMarginIfLarger(child->maxBottomMargin(true)); marginInfo.setNegMarginIfLarger(child->maxBottomMargin(false)); if (!marginInfo.canCollapseWithTop()) // 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 = height() + collapsedTopPos - collapsedTopNeg; } else { if (child->style()->marginTopCollapse() == MSEPARATE) { setHeight(height() + marginInfo.margin() + child->marginTop()); ypos = height(); } else if (!marginInfo.atTopOfBlock() || (!marginInfo.canCollapseTopWithChildren() && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) { // We're collapsing with a previous sibling's margins and not // with the top of the block. setHeight(height() + max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop)); ypos = height(); } marginInfo.setPosMargin(child->maxBottomMargin(true)); marginInfo.setNegMargin(child->maxBottomMargin(false)); if (marginInfo.margin()) marginInfo.setBottomQuirk(child->isBottomMarginQuirk() || style()->marginBottomCollapse() == MDISCARD); marginInfo.setSelfCollapsingBlockClearedFloat(false); } return ypos;}int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos){ int heightIncrease = getClearDelta(child, yPos); if (!heightIncrease) return yPos; if (child->isSelfCollapsingBlock()) { // For self-collapsing blocks that clear, they can still collapse their // margins with following siblings. Reset the current margins to represent // the self-collapsing block's margins only. marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true))); marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false))); // Adjust our height such that we are ready to be collapsed with subsequent siblings. setHeight(child->y() - max(0, marginInfo.margin())); // Set a flag that we cleared a float so that we know both to increase the height of the block // to compensate for the clear and to avoid collapsing our margins with the parent block's // bottom margin. marginInfo.setSelfCollapsingBlockClearedFloat(true); } else // Increase our height by the amount we had to clear. setHeight(height() + heightIncrease); if (marginInfo.canCollapseWithTop()) { // We can no longer collapse with the top of the block since a clear // occurred. The empty blocks collapse into the cleared block. // FIXME: This isn't quite correct. Need clarification for what to do // if the height the cleared block is offset by is smaller than the // margins involved. setMaxTopMargins(oldTopPosMargin, oldTopNegMargin); marginInfo.setAtTopOfBlock(false); } return yPos + heightIncrease;}int RenderBlock::estimateVerticalPosition(RenderBox* child, const MarginInfo& marginInfo){ // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological // relayout if there are intruding floats. int yPosEstimate = height(); if (!marginInfo.canCollapseWithTop()) { int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop(); yPosEstimate += max(marginInfo.margin(), childMarginTop); } yPosEstimate += getClearDelta(child, yPosEstimate); return yPosEstimate;}void RenderBlock::determineHorizontalPosition(RenderBox* child){ if (style()->direction() == LTR) { int xPos = borderLeft() + paddingLeft(); // Add in our left margin. int chPos = xPos + child->marginLeft(); // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need // to shift over as necessary to dodge any floats that might get in the way. if (child->avoidsFloats()) { int leftOff = leftOffset(height(), false); if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginLeft().type() != Auto) { if (child->marginLeft() < 0) leftOff += child->marginLeft(); chPos = max(chPos, leftOff); // Let the float sit in the child's margin if it can fit. } else if (leftOff != xPos) { // The object is shifting right. The object might be centered, so we need to // recalculate our horizontal margins. Note that the containing block content // width computation will take into account the delta between |leftOff| and |xPos| // so that we can just pass the content width in directly to the |calcHorizontalMargins| // function. child->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->y(), false)); chPos = leftOff + child->marginLeft(); } } view()->addLayoutDelta(IntSize(child->x() - chPos, 0)); child->setLocation(chPos, child->y()); } else { int xPos = width() - borderRight() - paddingRight() - verticalScrollbarWidth(); int chPos = xPos - (child->width() + child->marginRight()); if (child->avoidsFloats()) { int rightOff = rightOffset(height(), false); if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginRight().type() != Auto) { if (child->marginRight() < 0) rightOff -= child->marginRight(); chPos = min(chPos, rightOff - child->width()); // Let the float sit in the child's margin if it can fit. } else if (rightOff != xPos) { // The object is shifting left. The object might be centered, so we need to // recalculate our horizontal margins. Note that the containing block content // width computation will take into account the delta between |rightOff| and |xPos| // so that we can just pass the content width in directly to the |calcHorizontalMargins| // function. child->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->y(), false)); chPos = rightOff - child->marginRight() - child->width(); } } view()->addLayoutDelta(IntSize(child->x() - chPos, 0)); child->setLocation(chPos, child->y()); }}void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo){ if (marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()) { // Update our max pos/neg bottom margins, since we collapsed our bottom margins // with our children. setMaxBottomMargins(max(maxBottomPosMargin(), marginInfo.posMargin()), max(maxBottomNegMargin(), marginInfo.negMargin())); if (!marginInfo.bottomQuirk()) setBottomMarginQuirk(false);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -