📄 render_block.cpp
字号:
{ // Beginning at |start| we find the largest contiguous run of inlines that // we can. We denote the run with start and end points, |inlineRunStart| // and |inlineRunEnd|. Note that these two values may be the same if // we encounter only one inline. // // We skip any non-inlines we encounter as long as we haven't found any // inlines yet. // // |stop| indicates a non-inclusive stop point. Regardless of whether |stop| // is inline or not, we will not include it. It's as though we encountered // a non-inline. inlineRunStart = inlineRunEnd = 0; // Start by skipping as many non-inlines as we can. RenderObject * curr = start; while (curr && !curr->isInline()) curr = curr->nextSibling(); if (!curr) return; // No more inline children to be found. inlineRunStart = inlineRunEnd = curr; curr = curr->nextSibling(); while (curr && curr->isInline() && (curr != stop)) { inlineRunEnd = curr; curr = curr->nextSibling(); }}void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint){ // makeChildrenNonInline takes a block whose children are *all* inline and it // makes sure that inline children are coalesced under anonymous // blocks. If |insertionPoint| is defined, then it represents the insertion point for // the new block child that is causing us to have to wrap all the inlines. This // means that we cannot coalesce inlines before |insertionPoint| with inlines following // |insertionPoint|, because the new child is going to be inserted in between the inlines, // splitting them. KHTMLAssert(isReplacedBlock() || !isInline()); KHTMLAssert(!insertionPoint || insertionPoint->parent() == this); m_childrenInline = false; RenderObject *child = firstChild(); while (child) { RenderObject *inlineRunStart, *inlineRunEnd; getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd); if (!inlineRunStart) break; child = inlineRunEnd->nextSibling(); RenderBlock* box = createAnonymousBlock(); insertChildNode(box, inlineRunStart); RenderObject* o = inlineRunStart; while(o != inlineRunEnd) { RenderObject* no = o; o = no->nextSibling(); box->appendChildNode(removeChildNode(no)); } box->appendChildNode(removeChildNode(inlineRunEnd)); box->close(); box->setPos(box->xPos(), -500000); }}void RenderBlock::makePageBreakAvoidBlocks(){ KHTMLAssert(!childrenInline()); KHTMLAssert(canvas()->pagedMode()); RenderObject *breakAfter = firstChild(); RenderObject *breakBefore = breakAfter ? breakAfter->nextSibling() : 0; RenderBlock* pageRun = 0; // ### Should follow margin-collapsing rules, skipping self-collapsing blocks // and exporting page-breaks from first/last child when collapsing with parent margin. while (breakAfter) { if (breakAfter->isRenderBlock() && !breakAfter->childrenInline()) static_cast<RenderBlock*>(breakAfter)->makePageBreakAvoidBlocks(); EPageBreak pbafter = breakAfter->style()->pageBreakAfter(); EPageBreak pbbefore = breakBefore ? breakBefore->style()->pageBreakBefore() : PBALWAYS; if ((pbafter == PBAVOID && pbbefore == PBAVOID) || (pbafter == PBAVOID && pbbefore == PBAUTO) || (pbafter == PBAUTO && pbbefore == PBAVOID)) { if (!pageRun) { pageRun = createAnonymousBlock(); pageRun->m_avoidPageBreak = true; pageRun->setChildrenInline(false); } pageRun->appendChildNode(removeChildNode(breakAfter)); } else { if (pageRun) { pageRun->appendChildNode(removeChildNode(breakAfter)); pageRun->close(); insertChildNode(pageRun, breakBefore); pageRun = 0; } } breakAfter = breakBefore; breakBefore = breakBefore ? breakBefore->nextSibling() : 0; } // recurse into positioned block children as well. if (m_positionedObjects) { QPtrListIterator<RenderObject> it(*m_positionedObjects); for ( ; it.current(); ++it ) { if (it.current()->isRenderBlock() && !it.current()->childrenInline()) { static_cast<RenderBlock*>(it.current())->makePageBreakAvoidBlocks(); } } } // recurse into floating block children. if (m_floatingObjects) { QPtrListIterator<FloatingObject> it(*m_floatingObjects); for ( ; it.current(); ++it ) { if (it.current()->node->isRenderBlock() && !it.current()->node->childrenInline()) { static_cast<RenderBlock*>(it.current()->node)->makePageBreakAvoidBlocks(); } } }}void RenderBlock::removeChild(RenderObject *oldChild){ // If this child is a block, and if our previous and next siblings are // both anonymous blocks with inline content, then we can go ahead and // fold the inline content back together. RenderObject* prev = oldChild->previousSibling(); RenderObject* next = oldChild->nextSibling(); bool mergedBlocks = false; if (document()->renderer() && !isInline() && !oldChild->isInline() && !oldChild->continuation() && prev && prev->isAnonymousBlock() && prev->childrenInline() && next && next->isAnonymousBlock() && next->childrenInline()) { // Take all the children out of the |next| block and put them in // the |prev| block. RenderObject* o = next->firstChild(); while (o) { RenderObject* no = o; o = no->nextSibling(); prev->appendChildNode(next->removeChildNode(no)); no->setNeedsLayoutAndMinMaxRecalc(); } prev->setNeedsLayoutAndMinMaxRecalc(); // Nuke the now-empty block. next->detach(); mergedBlocks = true; } RenderFlow::removeChild(oldChild); if (mergedBlocks && prev && !prev->previousSibling() && !prev->nextSibling()) { // The remerge has knocked us down to containing only a single anonymous // box. We can go ahead and pull the content right back up into our // box. RenderObject* anonBlock = removeChildNode(prev); m_childrenInline = true; RenderObject* o = anonBlock->firstChild(); while (o) { RenderObject* no = o; o = no->nextSibling(); appendChildNode(anonBlock->removeChildNode(no)); no->setNeedsLayoutAndMinMaxRecalc(); } // Nuke the now-empty block. anonBlock->detach(); }}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 if (m_height > 0 || isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 || style()->minHeight().value() > 0) return false; bool hasAutoHeight = style()->height().isVariable(); if (style()->height().isPercent() && !style()->htmlHacks()) { hasAutoHeight = true; for (RenderBlock* cb = containingBlock(); !cb->isCanvas(); 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().value() == 0)) { // 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 (RenderObject* child = firstChild(); child; child = child->nextSibling()) { if (child->isFloatingOrPositioned()) continue; if (!child->isSelfCollapsingBlock()) return false; } return true; } return false;}void RenderBlock::layout(){ // Table cells call layoutBlock directly, so don't add any logic here. Put code into // layoutBlock(). layoutBlock(false);}void RenderBlock::layoutBlock(bool relayoutChildren){ if (isInline() && !isReplacedBlock()) { setNeedsLayout(false); return; } // kdDebug( 6040 ) << renderName() << " " << this << "::layoutBlock() start" << endl; // QTime t; // t.start(); KHTMLAssert( needsLayout() ); KHTMLAssert( minMaxKnown() ); if (canvas()->pagedMode()) relayoutChildren = true; if (!relayoutChildren && posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) { // All we have to is lay out our positioned objects. layoutPositionedObjects(relayoutChildren); if (hasOverflowClip()) m_layer->checkScrollbarsAfterLayout(); setNeedsLayout(false); return; } if (markedForRepaint()) { repaintDuringLayout(); setMarkedForRepaint(false); } int oldWidth = m_width; calcWidth(); m_overflowWidth = m_width; if ( oldWidth != m_width ) relayoutChildren = true; // kdDebug( 6040 ) << floatingObjects << "," << oldWidth << "," // << m_width << ","<< needsLayout() << "," << isAnonymousBox() << "," // << overhangingContents() << "," << isPositioned() << endl;#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << renderName() << "(RenderBlock) " << this << " ::layout() width=" << m_width << ", needsLayout=" << needsLayout() << endl; if(containingBlock() == static_cast<RenderObject *>(this)) kdDebug( 6040 ) << renderName() << ": containingBlock == this" << endl;#endif clearFloats(); m_height = 0; m_overflowHeight = 0; m_clearStatus = CNONE; // 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. if (!isTableCell()) { initMaxMarginValues(); m_topMarginQuirk = style()->marginTop().isQuirk(); m_bottomMarginQuirk = style()->marginBottom().isQuirk(); if (element() && element()->id() == ID_FORM && static_cast<HTMLFormElementImpl*>(element())->isMalformed()) // See if this form is malformed (i.e., unclosed). If so, don't give the form // a bottom margin. m_maxBottomPosMargin = m_maxBottomNegMargin = 0; } if (style()->scrollsOverflow() && m_layer) { // For overflow:scroll blocks, ensure we have both scrollbars in place always. if (style()->overflow() == OSCROLL) { m_layer->showScrollbar( Qt::Horizontal, true ); m_layer->showScrollbar( Qt::Vertical, true ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -