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

📄 render_block.cpp

📁 konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版本源码包.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    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 = kMax(posTop, (int)child->maxBottomMargin(true));        negTop = kMax(negTop, (int)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) {            m_maxTopPosMargin = kMax(posTop, (int)m_maxTopPosMargin);            m_maxTopNegMargin = kMax(negTop, (int)m_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)) {            m_topMarginQuirk = 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.            m_topMarginQuirk = true;    }    if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop))        marginInfo.setTopQuirk(topQuirk);    int ypos = m_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 = kMax(marginInfo.posMargin(), (int)child->maxTopMargin(true));        int collapsedTopNeg = kMax(marginInfo.negMargin(), (int)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 = m_height + collapsedTopPos - collapsedTopNeg;    }    else {#ifdef APPLE_CHANGES        if (child->style()->marginTopCollapse() == MSEPARATE) {            m_height += marginInfo.margin() + child->marginTop();            ypos = m_height;        }        else#endif        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.            m_height += kMax(marginInfo.posMargin(), posTop) - kMax(marginInfo.negMargin(), negTop);            ypos = m_height;        }        marginInfo.setPosMargin(child->maxBottomMargin(true));        marginInfo.setNegMargin(child->maxBottomMargin(false));        if (marginInfo.margin())            marginInfo.setBottomQuirk(child->isBottomMarginQuirk() /*|| style()->marginBottomCollapse() == MDISCARD*/);        marginInfo.setSelfCollapsingBlockClearedFloat(false);    }    child->setPos(child->xPos(), ypos);    if (ypos != yPosEstimate) {        if (child->style()->width().isPercent() && child->usesLineWidth())            // The child's width is a percentage of the line width.            // When the child shifts to clear an item, its width can            // change (because it has more available line width).            // So go ahead and mark the item as dirty.            child->setChildNeedsLayout(true);        if (!child->flowAroundFloats() || child->hasFloats())            child->markAllDescendantsWithFloatsForLayout();        // Our guess was wrong. Make the child lay itself out again.        child->layoutIfNeeded();    }}void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin){    int heightIncrease = getClearDelta(child);    if (heightIncrease) {        // The child needs to be lowered.  Move the child so that it just clears the float.        child->setPos(child->xPos(), child->yPos() + heightIncrease);        // Increase our height by the amount we had to clear.        if (!child->isSelfCollapsingBlock())            m_height += heightIncrease;        else {            // For self-collapsing blocks that clear, they may end up collapsing            // into the bottom of the parent block.  We simulate this behavior by            // setting our positive margin value to compensate for the clear.            marginInfo.setPosMargin(kMax(0, child->yPos() - m_height));            marginInfo.setNegMargin(0);            marginInfo.setSelfCollapsingBlockClearedFloat(true);        }        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.            m_maxTopPosMargin = oldTopPosMargin;            m_maxTopNegMargin = oldTopNegMargin;            marginInfo.setAtTopOfBlock(false);        }        // If our value of clear caused us to be repositioned vertically to be        // underneath a float, we might have to do another layout to take into account        // the extra space we now have available.        if (!child->style()->width().isFixed()  && child->usesLineWidth())            // The child's width is a percentage of the line width.            // When the child shifts to clear an item, its width can            // change (because it has more available line width).            // So go ahead and mark the item as dirty.            child->setChildNeedsLayout(true);        if (child->hasFloats())            child->markAllDescendantsWithFloatsForLayout();        child->layoutIfNeeded();    }}bool RenderBlock::canClear(RenderObject *child, PageBreakLevel level){    KHTMLAssert(child->parent() && child->parent() == this);    KHTMLAssert(canvas()->pagedMode());    // Positioned elements cannot be moved. Only normal flow and floating.    if (child->isPositioned() || child->isRelPositioned()) return false;    switch(level) {        case PageBreakNormal:            // check page-break-inside: avoid            if (!style()->pageBreakInside())                // we cannot, but can our parent?                if(!parent()->canClear(this, level)) return false;        case PageBreakHarder:            // check page-break-after/before: avoid            if (m_avoidPageBreak)                // we cannot, but can our parent?                if(!parent()->canClear(this, level)) return false;        case PageBreakForced:            // child is larger than page-height and is forced to break            if(child->height() > canvas()->pageHeight()) return false;            return true;    }    assert(false);    return false;}void RenderBlock::clearPageBreak(RenderObject* child, int pageBottom){    KHTMLAssert(child->parent() && child->parent() == this);    KHTMLAssert(canvas()->pagedMode());    if (child->yPos() >= pageBottom) return;    int heightIncrease = 0;    heightIncrease = pageBottom - child->yPos();    // ### should never happen, canClear should have been called to detect it.    if (child->height() > canvas()->pageHeight()) {        kdDebug(6040) << "### child is too large to clear: " << child->height() << " > " << canvas()->pageHeight() << endl;        return;    }    // The child needs to be lowered.  Move the child so that it just clears the break.    child->setPos(child->xPos(), pageBottom);#ifdef PAGE_DEBUG    kdDebug(6040) << "Cleared block " << heightIncrease << "px" << endl;#endif    // Increase our height by the amount we had to clear.    m_height += heightIncrease;    // We might have to do another layout to take into account    // the extra space we now have available.    if (!child->style()->width().isFixed()  && child->usesLineWidth())        // The child's width is a percentage of the line width.        // When the child shifts to clear a page-break, its width can        // change (because it has more available line width).        // So go ahead and mark the item as dirty.        child->setChildNeedsLayout(true);    if (child->hasFloats())        child->markAllDescendantsWithFloatsForLayout();    if (child->containsPageBreak())        child->setNeedsLayout(true);    child->layoutIfNeeded();    child->setAfterPageBreak(true);}int RenderBlock::estimateVerticalPosition(RenderObject* 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 = m_height;    if (!marginInfo.canCollapseWithTop()) {        int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop();        yPosEstimate += kMax(marginInfo.margin(), childMarginTop);    }    return yPosEstimate;}void RenderBlock::determineHorizontalPosition(RenderObject* 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->flowAroundFloats()) {            int leftOff = leftOffset(m_height);            if (style()->textAlign() != KHTML_CENTER && !child->style()->marginLeft().isVariable()) {                if (child->marginLeft() < 0)                    leftOff += child->marginLeft();                chPos = kMax(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.                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();        if (m_layer && style()->scrollsOverflow())            xPos -= m_layer->verticalScrollbarWidth();        int chPos = xPos - (child->width() + child->marginRight());        if (child->flowAroundFloats()) {            int rightOff = rightOffset(m_height);            if (style()->textAlign() != KHTML_CENTER && !child->style()->marginRight().isVariable()) {                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((int)m_maxBottomPosMargin, marginInfo.posMargin());        m_maxBottomNegMargin = kMax((int)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;    }}

⌨️ 快捷键说明

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