📄 renderblock.cpp
字号:
shadowTop = min(boxShadow->y - boxShadow->blur, shadowTop); shadowBottom = max(boxShadow->y + boxShadow->blur, shadowBottom); } box.move(shadowLeft, shadowTop); box.setWidth(box.width() - shadowLeft + shadowRight); box.setHeight(box.height() - shadowTop + shadowBottom); if (hasReflection()) { IntRect reflection(reflectionBox()); int reflectTop = min(box.y(), reflection.y()); int reflectBottom = max(box.bottom(), reflection.bottom()); box.setHeight(reflectBottom - reflectTop); box.setY(reflectTop); int reflectLeft = min(box.x(), reflection.x()); int reflectRight = max(box.right(), reflection.right()); box.setWidth(reflectRight - reflectLeft); box.setX(reflectLeft); } return box; } if (!includeInterior && hasOverflowClip()) return borderBoxRect(); int l = overflowLeft(includeInterior); int t = overflowTop(includeInterior); return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height()) - t);}bool RenderBlock::isSelfCollapsingBlock() const{ // We are not self-collapsing if we // (a) have a non-zero height according to layout (an optimization to avoid wasting time) // (b) are a table, // (c) have border/padding, // (d) have a min-height // (e) have specified that one of our margins can't collapse using a CSS extension if (height() > 0 || isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 || style()->minHeight().isPositive() || style()->marginTopCollapse() == MSEPARATE || style()->marginBottomCollapse() == MSEPARATE) return false; bool hasAutoHeight = style()->height().isAuto(); if (style()->height().isPercent() && !style()->htmlHacks()) { hasAutoHeight = true; for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) { if (cb->style()->height().isFixed() || cb->isTableCell()) hasAutoHeight = false; } } // If the height is 0 or auto, then whether or not we are a self-collapsing block depends // on whether we have content that is all self-collapsing or not. if (hasAutoHeight || ((style()->height().isFixed() || style()->height().isPercent()) && style()->height().isZero())) { // If the block has inline children, see if we generated any line boxes. If we have any // line boxes, then we can't be self-collapsing, since we have content. if (childrenInline()) return !firstLineBox(); // Whether or not we collapse is dependent on whether all our normal flow children // are also self-collapsing. for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { if (child->isFloatingOrPositioned()) continue; if (!child->isSelfCollapsingBlock()) return false; } return true; } return false;}void RenderBlock::layout(){ // Update our first letter info now. updateFirstLetter(); // Table cells call layoutBlock directly, so don't add any logic here. Put code into // layoutBlock(). layoutBlock(false); // It's safe to check for control clip here, since controls can never be table cells. if (hasControlClip()) { // Because of the lightweight clip, there can never be any overflow from children. m_overflowWidth = width(); m_overflowHeight = height(); m_overflowLeft = 0; m_overflowTop = 0; }}void RenderBlock::layoutBlock(bool relayoutChildren){ ASSERT(needsLayout()); if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can return; // cause us to come in here. Just bail. if (!relayoutChildren && layoutOnlyPositionedObjects()) return; LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout()); LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection()); int oldWidth = width(); int oldColumnWidth = desiredColumnWidth(); calcWidth(); calcColumnWidth(); m_overflowWidth = width(); m_overflowLeft = 0; if (oldWidth != width() || oldColumnWidth != desiredColumnWidth()) relayoutChildren = true; clearFloats(); int previousHeight = height(); setHeight(0); m_overflowHeight = 0; // We use four values, maxTopPos, maxPosNeg, maxBottomPos, and maxBottomNeg, to track // our current maximal positive and negative margins. These values are used when we // are collapsed with adjacent blocks, so for example, if you have block A and B // collapsing together, then you'd take the maximal positive margin from both A and B // and subtract it from the maximal negative margin from both A and B to get the // true collapsed margin. This algorithm is recursive, so when we finish layout() // our block knows its current maximal positive/negative values. // // Start out by setting our margin values to our current margins. Table cells have // no margins, so we don't fill in the values for table cells. bool isCell = isTableCell(); if (!isCell) { initMaxMarginValues(); setTopMarginQuirk(style()->marginTop().quirk()); setBottomMarginQuirk(style()->marginBottom().quirk()); Node* n = node(); if (n && n->hasTagName(formTag) && static_cast<HTMLFormElement*>(n)->isMalformed()) { // See if this form is malformed (i.e., unclosed). If so, don't give the form // a bottom margin. setMaxBottomMargins(0, 0); } } // For overflow:scroll blocks, ensure we have both scrollbars in place always. if (scrollsOverflow()) { if (style()->overflowX() == OSCROLL) layer()->setHasHorizontalScrollbar(true); if (style()->overflowY() == OSCROLL) layer()->setHasVerticalScrollbar(true); } int repaintTop = 0; int repaintBottom = 0; int maxFloatBottom = 0; if (childrenInline()) layoutInlineChildren(relayoutChildren, repaintTop, repaintBottom); else layoutBlockChildren(relayoutChildren, maxFloatBottom); // Expand our intrinsic height to encompass floats. int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); if (floatBottom() > (height() - toAdd) && expandsToEncloseOverhangingFloats()) setHeight(floatBottom() + toAdd); // Now lay out our columns within this intrinsic height, since they can slightly affect the intrinsic height as // we adjust for clean column breaks. int singleColumnBottom = layoutColumns(); // Calculate our new height. int oldHeight = height(); calcHeight(); if (oldHeight != height()) { if (oldHeight > height() && maxFloatBottom > height() && !childrenInline()) { // One of our children's floats may have become an overhanging float for us. We need to look for it. for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { if (child->isBlockFlow() && !child->isFloatingOrPositioned()) { RenderBlock* block = toRenderBlock(child); if (block->floatBottom() + block->y() > height()) addOverhangingFloats(block, -block->x(), -block->y(), false); } } } // We have to rebalance columns to the new height. layoutColumns(singleColumnBottom); // If the block got expanded in size, then increase our overflowheight to match. if (m_overflowHeight > height()) m_overflowHeight -= toAdd; if (m_overflowHeight < height()) m_overflowHeight = height(); } if (previousHeight != height()) relayoutChildren = true; if ((isCell || isInline() || isFloatingOrPositioned() || isRoot()) && !hasOverflowClip() && !hasControlClip()) addVisualOverflow(floatRect()); layoutPositionedObjects(relayoutChildren || isRoot()); positionListMarker(); // Always ensure our overflow width/height are at least as large as our width/height. m_overflowWidth = max(m_overflowWidth, width()); m_overflowHeight = max(m_overflowHeight, height()); if (!hasOverflowClip()) { for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) { m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur); m_overflowWidth = max(m_overflowWidth, width() + boxShadow->x + boxShadow->blur); m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur); m_overflowHeight = max(m_overflowHeight, height() + boxShadow->y + boxShadow->blur); } if (hasReflection()) { m_overflowTop = min(m_overflowTop, reflectionBox().y()); m_overflowHeight = max(m_overflowHeight, reflectionBox().bottom()); } } statePusher.pop(); // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if // we overflow or not. if (hasOverflowClip()) layer()->updateScrollInfoAfterLayout(); // Repaint with our new bounds if they are different from our old bounds. bool didFullRepaint = repainter.repaintAfterLayout(); if (!didFullRepaint && repaintTop != repaintBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) { IntRect repaintRect(m_overflowLeft, repaintTop, m_overflowWidth - m_overflowLeft, repaintBottom - repaintTop); // FIXME: Deal with multiple column repainting. We have to split the repaint // rect up into multiple rects if it spans columns. repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline)); if (hasOverflowClip()) { // Adjust repaint rect for scroll offset int x = repaintRect.x(); int y = repaintRect.y(); layer()->subtractScrolledContentOffset(x, y); repaintRect.setX(x); repaintRect.setY(y); // Don't allow this rect to spill out of our overflow box. repaintRect.intersect(IntRect(0, 0, width(), height())); } // Make sure the rect is still non-empty after intersecting for overflow above if (!repaintRect.isEmpty()) { repaintRectangle(repaintRect); // We need to do a partial repaint of our content. if (hasReflection()) layer()->reflection()->repaintRectangle(repaintRect); } } setNeedsLayout(false);}bool RenderBlock::expandsToEncloseOverhangingFloats() const{ return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox()) || hasColumns() || isTableCell() || isFieldset();}void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo){ if (child->style()->hasStaticX()) { if (style()->direction() == LTR) child->layer()->setStaticX(borderLeft() + paddingLeft()); else child->layer()->setStaticX(borderRight() + paddingRight()); } if (child->style()->hasStaticY()) { int y = height(); if (!marginInfo.canCollapseWithTop()) { child->calcVerticalMargins(); int marginTop = child->marginTop(); int collapsedTopPos = marginInfo.posMargin(); int collapsedTopNeg = marginInfo.negMargin(); if (marginTop > 0) { if (marginTop > collapsedTopPos) collapsedTopPos = marginTop; } else { if (-marginTop > collapsedTopNeg) collapsedTopNeg = -marginTop; } y += (collapsedTopPos - collapsedTopNeg) - marginTop; } child->layer()->setStaticY(y); }}void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo){ // 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -