⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 render_block.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                // 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.
                static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
                chPos = leftOff + child->marginLeft();
            }
        }
        child->setPos(chPos, child->yPos());
    } else {
        int xPos = m_width - borderRight() - paddingRight() - (includeScrollbarSize() ? m_layer->verticalScrollbarWidth() : 0);
        int chPos = xPos - (child->width() + child->marginRight());
        if (child->avoidsFloats()) {
            int rightOff = rightOffset(m_height);
            if (style()->textAlign() != KHTML_CENTER && child->style()->marginRight().type != Variable) {
                if (child->marginRight() < 0)
                    rightOff -= child->marginRight();
                chPos = kMin(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.
                static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
                chPos = rightOff - child->marginRight() - child->width();
            }
        }
        child->setPos(chPos, child->yPos());
    }
}

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.
        m_maxBottomPosMargin = kMax(m_maxBottomPosMargin, marginInfo.posMargin());
        m_maxBottomNegMargin = kMax(m_maxBottomNegMargin, marginInfo.negMargin());

        if (!marginInfo.bottomQuirk())
            m_bottomMarginQuirk = false;

        if (marginInfo.bottomQuirk() && marginBottom() == 0)
            // We have no bottom margin and our last child has a quirky margin.
            // We will pick up this quirky margin and pass it through.
            // This deals with the <td><div><p> case.
            m_bottomMarginQuirk = true;
    }
}

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)
{
    int top = borderTop() + paddingTop();
    int bottom = borderBottom() + paddingBottom() + (includeScrollbarSize() ? m_layer->horizontalScrollbarHeight() : 0);

    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);

    RenderObject* child = firstChild();
    while (child) {
        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 layout children if they need it.
        // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
        // an auto value.  Add a method to determine this, so that we can avoid the relayout.
        if (relayoutChildren || 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();

        // 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();
        }

        // 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->avoidsFloats() || child->usesLineWidth()) {
            int fb = floatBottom();
            if (fb > m_height || fb > yPosEstimate)
                child->setChildNeedsLayout(true);
        }

        // Cache our old position so that we can dirty the proper repaint rects if the child moves.
        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.
        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 top overflow in case the child spills out the top of the block.
        m_overflowTop = kMin(m_overflowTop, child->yPos() + child->overflowTop(false));

        // Update our height now that the child has been placed in the correct position.
        m_height += child->height();
        if (child->style()->marginBottomCollapse() == MSEPARATE) {
            m_height += child->marginBottom();
            marginInfo.clearMargin();
        }
        int overflowDelta = child->overflowHeight(false) - child->height();
        if (m_height + overflowDelta > m_overflowHeight)
            m_overflowHeight = m_height + overflowDelta;

        // If the child has overhanging floats that intrude into following siblings (or possibly out
        // of this block), then the parent gets notified of the floats now.
        addOverhangingFloats(static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos());

        // See if this child has made our overflow need to grow.
        int rightChildPos = child->xPos() + kMax(child->overflowWidth(false), child->width());
        m_overflowWidth = kMax(rightChildPos, m_overflowWidth);
        m_overflowLeft = kMin(child->xPos() + child->overflowLeft(false), m_overflowLeft);

        // Insert our compact into the block margin if we have one.
        insertCompactIfNeeded(child, compactInfo);

        // If the child moved, we have to repaint it as well as any floating/positioned
        // descendants.  An exception is if we need a layout.  In this case, we know we're going to
        // repaint ourselves (and the child) anyway.
        if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
            child->repaintDuringLayoutIfMoved(oldChildX, oldChildY);

        child = child->nextSibling();
    }

    // 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);

    // Finished. Clear the dirty layout bits.
    setNeedsLayout(false);
}

void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
{
    if (m_positionedObjects) {
        //kdDebug( 6040 ) << renderName() << " " << this << "::layoutPositionedObjects() start" << endl;
        RenderObject* r;
        QPtrListIterator<RenderObject> it(*m_positionedObjects);
        for ( ; (r = it.current()); ++it ) {
            // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
            // non-positioned block.  Rather than trying to detect all of these movement cases, we just always lay out positioned
            // objects that are positioned implicitly like this.  Such objects are rare, and so in typical DHTML menu usage (where everything is
            // positioned explicitly) this should not incur a performance penalty.
            if (relayoutChildren || (r->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow()))
                r->setChildNeedsLayout(true);
            r->layoutIfNeeded();
        }
    }
}

void RenderBlock::markPositionedObjectsForLayout()
{
    if (m_positionedObjects) {
        RenderObject* r;
        QPtrListIterator<RenderObject> it(*m_positionedObjects);
        for (; (r = it.current()); ++it)
            r->setChildNeedsLayout(true);
    }
}

void RenderBlock::getAbsoluteRepaintRectIncludingFloats(QRect& bounds, QRect& fullBounds)
{
    bounds = fullBounds = getAbsoluteRepaintRect();

    // Include any overhanging floats (if we know we're the one to paint them).
    // We null-check m_floatingObjects here to catch any cases where m_height ends up negative
    // for some reason.  I think I've caught all those cases, but this way we stay robust and don't
    // crash.
    if (hasOverhangingFloats() && m_floatingObjects) {
        FloatingObject* r;
        QPtrListIterator<FloatingObject> it(*m_floatingObjects);
        for ( ; (r = it.current()); ++it) {
            // Only repaint the object if our noPaint flag isn't set and if it isn't in
            // its own layer.
            if (!r->noPaint && !r->node->layer()) {
                QRect childRect, childFullRect;
                r->node->getAbsoluteRepaintRectIncludingFloats(childRect, childFullRect);
                fullBounds = fullBounds.unite(childFullRect);
            }
        }
    }
}

void RenderBlock::repaintFloatingDescendants()
{
    // Repaint any overhanging floats (if we know we're the one to paint them).
    if (hasOverhangingFloats()) {
        FloatingObject* r;
        QPtrListIterator<FloatingObject> it(*m_floatingObjects);
        for ( ; (r = it.current()); ++it) {
            // Only repaint the object if our noPaint flag isn't set and if it isn't in
            // its own layer.
            if (!r->noPaint && !r->node->layer()) {
                r->node->repaint();
                r->node->repaintFloatingDescendants();
            }
        }
    }
}

void RenderBlock::repaintObjectsBeforeLayout()
{
    RenderFlow::repaintObjectsBeforeLayout();
    if (!needsLayout())
        return;

    // Walk our positioned objects.
    if (m_positionedObjects) {
        RenderObject* r;
        QPtrListIterator<RenderObject> it(*m_positionedObjects);
        for ( ; (r = it.current()); ++it )
            r->repaintObjectsBeforeLayout();
    }
}

#ifdef NOKIA_CHANGES
void RenderBlock::getRenderersInRect(QPtrList<BoxInfo>& boxInfoList,int deltaX,int deltaY,const QRect& rect)
{
    if (!isTableCell()){
	    deltaX += m_x;
	    deltaY += m_y;

	    // Check if we need to do anything at all.
	    if (!isInlineFlow() && !isRoot() && !isCanvas() && !isRoot() && !isBody()) {
		    QRect overflowBox = overflowRect(false);
		    overflowBox.setX(overflowBox.x() + deltaX);
		    overflowBox.setY(overflowBox.y() + deltaY);
		    bool intersectsOverflowBox = overflowBox.intersects(rect);
		    if (!intersectsOverflowBox) {
			    // Check floats next.
			    QRect floatBox = floatRect();
			    floatBox.setX(floatBox.x() + deltaX);
			    floatBox.setY(floatBox.y() + deltaY);
                if (!floatBox.intersects(rect))
				    return;
            }
        }
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -