📄 render_block.cpp
字号:
void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo){ // If our last flow was a self-collapsing block that cleared a float, then we don't // collapse it with the bottom of the block. if (!marginInfo.selfCollapsingBlockClearedFloat()) marginInfo.setAtBottomOfBlock(true); // If we can't collapse with children then go ahead and add in the bottom margin. if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop() && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk())) m_height += marginInfo.margin(); // Now add in our bottom border/padding. m_height += bottom; // Negative margins can cause our height to shrink below our minimal height (border/padding). // If this happens, ensure that the computed height is increased to the minimal height. m_height = kMax(m_height, top + bottom); // Always make sure our overflow height is at least our height. m_overflowHeight = kMax(m_height, m_overflowHeight); // Update our bottom collapsed margin info. setCollapsedBottomMargin(marginInfo);}void RenderBlock::layoutBlockChildren( bool relayoutChildren ){#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << renderName() << " layoutBlockChildren( " << this <<" ), relayoutChildren="<< relayoutChildren << endl;#endif int top = borderTop() + paddingTop(); int bottom = borderBottom() + paddingBottom(); if (m_layer && style()->scrollsOverflow()) bottom += m_layer->horizontalScrollbarHeight(); m_height = m_overflowHeight = top; // The margin struct caches all our current margin collapsing state. // The compact struct caches state when we encounter compacts. MarginInfo marginInfo(this, top, bottom); CompactInfo compactInfo; // Fieldsets need to find their legend and position it inside the border of the object. // The legend then gets skipped during normal layout. RenderObject* legend = layoutLegend(relayoutChildren); PageBreakInfo pageBreakInfo(pageTopAfter(0)); RenderObject* child = firstChild(); while( child != 0 ) { if (legend == child) { child = child->nextSibling(); continue; // Skip the legend, since it has already been positioned up in the fieldset's border. } int oldTopPosMargin = m_maxTopPosMargin; int oldTopNegMargin = m_maxTopNegMargin; // make sure we relayout children if we need it. if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())) || (child->isRenderBlock() && child->style()->height().isPercent())) child->setChildNeedsLayout(true); // Handle the four types of special elements first. These include positioned content, floating content, compacts and // run-ins. When we encounter these four types of objects, we don't actually lay them out as normal flow blocks. bool handled = false; RenderObject* next = handleSpecialChild(child, marginInfo, compactInfo, handled); if (handled) { child = next; continue; } // The child is a normal flow object. Compute its vertical margins now. child->calcVerticalMargins();#ifdef APPLE_CHANGES /* margin-*-collapse not merged yet */ // Do not allow a collapse if the margin top collapse style is set to SEPARATE. if (child->style()->marginTopCollapse() == MSEPARATE) { marginInfo.setAtTopOfBlock(false); marginInfo.clearMargin(); }#endif // 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 potentially relayout. int yPosEstimate = estimateVerticalPosition(child, marginInfo); // If an element might be affected by the presence of floats, then always mark it for // layout. if ( !child->flowAroundFloats() || child->usesLineWidth() ) { int fb = floatBottom(); if (fb > m_height || fb > yPosEstimate) child->setChildNeedsLayout(true); } // 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 on examination of collapsing margin // values. collapseMargins(child, marginInfo, yPosEstimate); // Now check for clear. clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin); // We are no longer at the top of the block if we encounter a non-empty child. // This has to be done after checking for clear, so that margins can be reset if a clear occurred. if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock()) marginInfo.setAtTopOfBlock(false); // Now place the child in the correct horizontal position determineHorizontalPosition(child); // Update our height now that the child has been placed in the correct position. m_height += child->height();#ifdef APPLE_CHANGES if (child->style()->marginBottomCollapse() == MSEPARATE) { m_height += child->marginBottom(); marginInfo.clearMargin(); }#endif // Check for page-breaks if (canvas()->pagedMode()) clearChildOfPageBreaks(child, pageBreakInfo, marginInfo); if (child->hasOverhangingFloats() && !child->flowAroundFloats()) { // need to add the child's floats to our floating objects list, but not in the case where // overflow is auto/scroll addOverHangingFloats( static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos(), true ); } // See if this child has made our overflow need to grow. // ### --dwh Work with left overflow as well as right overflow. int overflowDelta = - child->height() ; if ( child->isBlockFlow () && !child->isTable() && child->style()->hidesOverflow() ) overflowDelta += child->height(); else overflowDelta += child->overflowHeight(); // See if this child has made our overflow need to grow. int rightChildPos = child->xPos() + kMax(child->effectiveWidth(), (int)child->width()); if (child->isRelPositioned()) { // CSS 2.1-9.4.3 - allow access to relatively positioned content // ### left overflow support int xoff = 0, yoff = 0; static_cast<RenderBox*>(child)->relativePositionOffset(xoff, yoff); if (xoff>0) rightChildPos += xoff; if (yoff>0) overflowDelta += yoff; } m_overflowHeight = kMax(m_height + overflowDelta, m_overflowHeight); m_overflowWidth = kMax(rightChildPos, m_overflowWidth); // Insert our compact into the block margin if we have one. insertCompactIfNeeded(child, compactInfo); child = child->nextSibling(); } // The last child had forced page-break-after if (pageBreakInfo.forcePageBreak()) m_height = pageBreakInfo.pageBottom(); // Now do the handling of the bottom of the block, adding in our bottom border/padding and // determining the correct collapsed bottom margin information. handleBottomOfBlock(top, bottom, marginInfo); setNeedsLayout(false);}void RenderBlock::clearChildOfPageBreaks(RenderObject *child, PageBreakInfo &pageBreakInfo, MarginInfo &marginInfo){ int childTop = child->yPos(); int childBottom = child->yPos()+child->height();#ifdef PAGE_DEBUG kdDebug(6040) << renderName() << " ChildTop: " << childTop << " ChildBottom: " << childBottom << endl;#endif bool forcePageBreak = pageBreakInfo.forcePageBreak() || child->style()->pageBreakBefore() == PBALWAYS;#ifdef PAGE_DEBUG if (forcePageBreak) kdDebug(6040) << renderName() << "Forced break required" << endl;#endif int xpage = crossesPageBreak(childTop, childBottom); if (xpage || forcePageBreak) { if (!forcePageBreak && child->containsPageBreak() && !child->needsPageClear()) {#ifdef PAGE_DEBUG kdDebug(6040) << renderName() << " Child contains page-break to page " << xpage << endl;#endif // ### Actually this assumes floating children are breaking/clearing // nicely as well. setContainsPageBreak(true); } else { bool doBreak = true; // don't break before the first child or when page-break-inside is avoid if (!forcePageBreak && (!style()->pageBreakInside() || m_avoidPageBreak || child == firstChild())) { if (parent()->canClear(this, (m_avoidPageBreak) ? PageBreakHarder : PageBreakNormal )) {#ifdef PAGE_DEBUG kdDebug(6040) << renderName() << "Avoid page-break inside" << endl;#endif child->setNeedsPageClear(false); setNeedsPageClear(true); doBreak = false; }#ifdef PAGE_DEBUG else kdDebug(6040) << renderName() << "Ignoring page-break avoid" << endl;#endif } if (doBreak) {#ifdef PAGE_DEBUG kdDebug(6040) << renderName() << " Clearing child of page-break" << endl; kdDebug(6040) << renderName() << " child top of page " << xpage << endl;#endif clearPageBreak(child, pageBreakInfo.pageBottom()); child->setNeedsPageClear(false); setContainsPageBreak(true); } } pageBreakInfo.setPageBottom(pageBreakInfo.pageBottom() + canvas()->pageHeight()); } else if (child->yPos() >= pageBreakInfo.pageBottom()) { bool doBreak = true;#ifdef PAGE_DEBUG kdDebug(6040) << "Page-break between children" << endl;#endif if (!style()->pageBreakInside() || m_avoidPageBreak) { if(parent()->canClear(this, (m_avoidPageBreak) ? PageBreakHarder : PageBreakNormal )) {#ifdef PAGE_DEBUG kdDebug(6040) << "Avoid page-break inside" << endl;#endif child->setNeedsPageClear(false); setNeedsPageClear(true); doBreak = false; }#ifdef PAGE_DEBUG else kdDebug(6040) << "Ignoring page-break avoid" << endl;#endif } if (doBreak) { // Break between children setContainsPageBreak(true); // ### Should collapse top-margin with page-margin } pageBreakInfo.setPageBottom(pageBreakInfo.pageBottom() + canvas()->pageHeight()); } // Do we need a forced page-break before next child? pageBreakInfo.setForcePageBreak(false); if (child->style()->pageBreakAfter() == PBALWAYS) pageBreakInfo.setForcePageBreak(true);}void RenderBlock::layoutPositionedObjects(bool relayoutChildren){ if (m_positionedObjects) { //kdDebug( 6040 ) << renderName() << " " << this << "::layoutPositionedObjects() start" << endl; RenderObject* r; QPtrListIterator<RenderObject> it(*m_positionedObjects); bool adjOverflow = !(style()->position() == FIXED) && style()->hidesOverflow(); for ( ; (r = it.current()); ++it ) { //kdDebug(6040) << " have a positioned object" << endl; if (r->markedForRepaint()) { r->repaintDuringLayout(); r->setMarkedForRepaint(false); } if ( relayoutChildren || (r->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow()) ) r->setChildNeedsLayout(true); r->layoutIfNeeded(); if (adjOverflow && r->style()->position() == ABSOLUTE) { if (r->xPos() + r->effectiveWidth() > m_overflowWidth) m_overflowWidth = r->xPos() + r->effectiveWidth(); if (r->yPos() + r->effectiveHeight() > m_overflowHeight) m_overflowHeight = r->yPos() + r->effectiveHeight(); } } }}void RenderBlock::paint(PaintInfo& pI, int _tx, int _ty){ _tx += m_x; _ty += m_y; // check if we need to do anything at all... if (!isRoot() && !isInlineFlow() && !overhangingContents() && !isRelPositioned() && !isPositioned() ) { int h = m_overflowHeight; int yPos = _ty; if (m_floatingObjects && floatBottom() > h) h = floatBottom(); // Sanity check the first line // to see if it extended a little above our box. Overflow out the bottom is already handled via // overflowHeight(), so we don't need to check that. if (m_firstLineBox
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -