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

📄 render_box.cpp

📁 最新Nokia手机浏览器全套源代码完美版。
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        static_distance = m_staticX - cb->borderLeft(); // Should already have been set through layout of the parent().
        RenderObject* po = parent();
        for (; po && po != cb; po = po->parent())
            static_distance += po->xPos();

        if (l == AUTO || style()->left().isStatic())
            l = static_distance;
    }

    else if ((parent()->style()->direction()==RTL && (l==AUTO && r==AUTO ))
            || style()->right().isStatic())
    {
        RenderObject* po = parent();
        static_distance = m_staticX - cb->borderLeft(); // Should already have been set through layout of the parent().
        while (po && po!=containingBlock()) {
            static_distance+=po->xPos();
            po=po->parent();
        }

        if (r==AUTO || style()->right().isStatic())
            r = static_distance;
    }

    calcAbsoluteHorizontalValues(Width, cb, cw, pab, static_distance, l, r, m_width, m_marginLeft, m_marginRight, m_x);

    // Avoid doing any work in the common case (where the values of min-width and max-width are their defaults).
    int minW = m_width, minML, minMR, minX;
    calcAbsoluteHorizontalValues(MinWidth, cb, cw, pab, static_distance, l, r, minW, minML, minMR, minX);

    int maxW = m_width, maxML, maxMR, maxX;
    if (style()->maxWidth().value != UNDEFINED)
        calcAbsoluteHorizontalValues(MaxWidth, cb, cw, static_distance, pab, l, r, maxW, maxML, maxMR, maxX);

    if (m_width > maxW) {
        m_width = maxW;
        m_marginLeft = maxML;
        m_marginRight = maxMR;
        m_x = maxX;
    }

    if (m_width < minW) {
        m_width = minW;
        m_marginLeft = minML;
        m_marginRight = minMR;
        m_x = minX;
    }
}

void RenderBox::calcAbsoluteHorizontalValues(WidthType widthType, RenderObject* cb, int cw, int pab, int static_distance,
                                             int l, int r, int& w, int& ml, int& mr, int& x)
{
    const int AUTO = -666666;
    w = ml = mr = AUTO;

    if (!style()->marginLeft().isVariable())
        ml = style()->marginLeft().width(cw);
    if (!style()->marginRight().isVariable())
        mr = style()->marginRight().width(cw);

    Length width;
    if (widthType == Width)
        width = style()->width();
    else if (widthType == MinWidth)
        width = style()->minWidth();
    else
        width = style()->maxWidth();

    if (!width.isVariable())
        w = width.width(cw);
    else if (isReplaced())
        w = intrinsicWidth();

    if (l != AUTO && w != AUTO && r != AUTO) {
        // left, width, right all given, play with margins
        int ot = l + w + r + pab;

        if (ml==AUTO && mr==AUTO) {
            // both margins auto, solve for equality
            ml = (cw - ot)/2;
            mr = cw - ot - ml;
        }
        else if (ml==AUTO)
            // solve for left margin
            ml = cw - ot - mr;
        else if (mr==AUTO)
            // solve for right margin
            mr = cw - ot - ml;
        else {
            // overconstrained, solve according to dir
            if (style()->direction() == LTR)
                r = cw - ( l + w + ml + mr + pab);
            else
                l = cw - ( r + w + ml + mr + pab);
        }
    }
    else
    {
        // one or two of (left, width, right) missing, solve

        // auto margins are ignored
        if (ml==AUTO) ml = 0;
        if (mr==AUTO) mr = 0;

        //1. solve left & width.
        if (l == AUTO && w == AUTO && r != AUTO) {
            // From section 10.3.7 of the CSS2.1 specification.
            // "The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width)."
            w = kMin(kMax(m_minWidth - pab, cw - (r + ml + mr + pab)), m_maxWidth - pab);
            l = cw - (r + w + ml + mr + pab);
        }
        else

        //2. solve left & right. use static positioning.
        if (l == AUTO && w != AUTO && r == AUTO) {
            if (style()->direction()==RTL) {
                r = static_distance;
                l = cw - (r + w + ml + mr + pab);
            }
            else {
                l = static_distance;
                r = cw - (l + w + ml + mr + pab);
            }

        } //3. solve width & right.
        else if (l != AUTO && w == AUTO && r == AUTO) {
            // From section 10.3.7 of the CSS2.1 specification.
            // "The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width)."
            w = kMin(kMax(m_minWidth - pab, cw - (l + ml + mr + pab)), m_maxWidth - pab);
            r = cw - (l + w + ml + mr + pab);
        }
        else

        //4. solve left
        if (l==AUTO && w!=AUTO && r!=AUTO)
            l = cw - (r + w + ml + mr + pab);
        else
        //5. solve width
        if (l!=AUTO && w==AUTO && r!=AUTO)
            w = cw - (r + l + ml + mr + pab);
        else

        //6. solve right
        if (l!=AUTO && w!=AUTO && r==AUTO)
            r = cw - (l + w + ml + mr + pab);
    }

    w += pab;
    x = l + ml + cb->borderLeft();
}

void RenderBox::calcAbsoluteVertical()
{
    // css2 spec 10.6.4 & 10.6.5

    // based on
    // http://www.w3.org/Style/css2-updates/REC-CSS2-19980512-errata
    // (actually updated 2000-10-24)
    // that introduces static-position value for top, left & right

    const int AUTO = -666666;
    int t, b, ch;

    t = b = AUTO;

    int pab = borderTop()+borderBottom()+paddingTop()+paddingBottom();

    // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
    RenderObject* cb = container();
    if (cb->isRoot()) // Even in strict mode (where we don't grow the root to fill the viewport) other browsers
                      // position as though the root fills the viewport.
        ch = cb->availableHeight();
    else
        ch = cb->height() - cb->borderTop() - cb->borderBottom();

    if (!style()->top().isVariable())
        t = style()->top().width(ch);
    if (!style()->bottom().isVariable())
        b = style()->bottom().width(ch);

    int h, mt, mb, y;
    calcAbsoluteVerticalValues(Height, cb, ch, pab, t, b, h, mt, mb, y);

    // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
    int minH = h, minMT, minMB, minY;
    calcAbsoluteVerticalValues(MinHeight, cb, ch, pab, t, b, minH, minMT, minMB, minY);

    int maxH = h, maxMT, maxMB, maxY;
    if (style()->maxHeight().value != UNDEFINED)
        calcAbsoluteVerticalValues(MaxHeight, cb, ch, pab, t, b, maxH, maxMT, maxMB, maxY);

    if (h > maxH) {
        h = maxH;
        mt = maxMT;
        mb = maxMB;
        y = maxY;
    }

    if (h < minH) {
        h = minH;
        mt = minMT;
        mb = minMB;
        y = minY;
    }

    // If our natural height exceeds the new height once we've set it, then we need to make sure to update
    // overflow to track the spillout.
    if (m_height > h)
        setOverflowHeight(m_height);

    // Set our final values.
    m_height = h;
    m_marginTop = mt;
    m_marginBottom = mb;
    m_y = y;
}

void RenderBox::calcAbsoluteVerticalValues(HeightType heightType, RenderObject* cb, int ch, int pab,
                                           int t, int b, int& h, int& mt, int& mb, int& y)
{
    const int AUTO = -666666;
    h = mt = mb = AUTO;

    if (!style()->marginTop().isVariable())
        mt = style()->marginTop().width(ch);
    if (!style()->marginBottom().isVariable())
        mb = style()->marginBottom().width(ch);

    Length height;
    if (heightType == Height)
        height = style()->height();
    else if (heightType == MinHeight)
        height = style()->minHeight();
    else
        height = style()->maxHeight();

    int ourHeight = m_height;

    if (isTable() && height.isVariable())
        // Height is never unsolved for tables. "auto" means shrink to fit.  Use our
        // height instead.
        h = ourHeight - pab;
    else if (!height.isVariable())
    {
        h = height.width(ch);
        if (ourHeight - pab > h)
            ourHeight = h + pab;
    }
    else if (isReplaced())
        h = intrinsicHeight();

    int static_top=0;
    if ((t == AUTO && b == AUTO) || style()->top().isStatic()) {
        // calc hypothetical location in the normal flow
        // used for 1) top=static-position
        //          2) top, bottom, height are all auto -> calc top -> 3.
        //          3) precalc for case 2 below
        static_top = m_staticY - cb->borderTop(); // Should already have been set through layout of the parent().
        RenderObject* po = parent();
        for (; po && po != cb; po = po->parent())
            static_top += po->yPos();

        if (h == AUTO || style()->top().isStatic())
            t = static_top;
    }

    if (t != AUTO && h != AUTO && b != AUTO) {
        // top, height, bottom all given, play with margins
        int ot = h + t + b + pab;

        if (mt == AUTO && mb == AUTO) {
            // both margins auto, solve for equality
            mt = (ch - ot)/2;
            mb = ch - ot - mt;
        }
        else if (mt==AUTO)
            // solve for top margin
            mt = ch - ot - mb;
        else if (mb==AUTO)
            // solve for bottom margin
            mb = ch - ot - mt;
        else
            // overconstrained, solve for bottom
            b = ch - (h + t + mt + mb + pab);
    }
    else {
        // one or two of (top, height, bottom) missing, solve

        // auto margins are ignored
        if (mt == AUTO)
            mt = 0;
        if (mb == AUTO)
            mb = 0;

        //1. solve top & height. use content height.
        if (t == AUTO && h == AUTO && b != AUTO) {
            h = ourHeight - pab;
            t = ch - (h + b + mt + mb + pab);
        }
        else if (t == AUTO && h != AUTO && b == AUTO) //2. solve top & bottom. use static positioning.
        {
            t = static_top;
            b = ch - (h + t + mt + mb + pab);
        }
        else if (t != AUTO && h == AUTO && b == AUTO) //3. solve height & bottom. use content height.
        {
            h = ourHeight - pab;
            b = ch - (h + t + mt + mb + pab);
        }
        else
        //4. solve top
        if (t == AUTO && h != AUTO && b != AUTO)
            t = ch - (h + b + mt + mb + pab);
        else

        //5. solve height
        if (t != AUTO && h == AUTO && b != AUTO)
            h = ch - (t + b + mt + mb + pab);
        else

        //6. solve bottom
        if (t != AUTO && h != AUTO && b == AUTO)
            b = ch - (h + t + mt + mb + pab);
    }

    if (ourHeight < h + pab) //content must still fit
        ourHeight = h + pab;

    if (hasOverflowClip() && ourHeight > h + pab)
        ourHeight = h + pab;

    // Do not allow the height to be negative.  This can happen when someone specifies both top and bottom
    // but the containing block height is less than top, e.g., top:20px, bottom:0, containing block height 16.
    ourHeight = kMax(0, ourHeight);

    h = ourHeight;
    y = t + mt + cb->borderTop();
}

QRect RenderBox::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
{
    // FIXME: Is it OK to check only first child instead of picking
    // right child based on offset? Is it OK to pass the same offset
    // along to the child instead of offset 0 or whatever?

    // propagate it downwards to its children, someone will feel responsible
    RenderObject *child = firstChild();
    if (child) {
        QRect result = child->caretRect(offset, affinity, extraWidthToEndOfLine);
        // FIXME: in-band signalling!
        if (result.isEmpty())
            return result;
    }

    int _x, _y, height;

    // if not, use the extents of this box
    // offset 0 means left, offset 1 means right
    _x = xPos() + (offset == 0 ? 0 : m_width);
    InlineBox *box = inlineBoxWrapper();
    if (box) {
        height = box->root()->bottomOverflow() - box->root()->topOverflow();
        _y = box->root()->topOverflow();
    }
    else {
        _y = yPos();
        height = m_height;
    }
    // If height of box is smaller than font height, use the latter one,
    // otherwise the caret might become invisible.
    //
    // Also, if the box is not a replaced element, always use the font height.
    // This prevents the "big caret" bug described in:
    // <rdar://problem/3777804> Deleting all content in a document can result in giant tall-as-window insertion point
    //
    // FIXME: ignoring :first-line, missing good reason to take care of
    int fontHeight = style()->fontMetrics().height();
    if (fontHeight > height || !isReplaced())
        height = fontHeight;

    int absx, absy;
    RenderObject *cb = containingBlock();
    if (cb && cb != this && cb->absolutePosition(absx,absy)) {
        _x += absx;
        _y += absy;
    }
    else {
        // we don't know our absolute position, and there is no point returning
        // just a relative one
        return QRect();
    }

    if (extraWidthToEndOfLine)
        *extraWidthToEndOfLine = m_width - _x;

    return QRect(_x, _y, 1, height);
}

int RenderBox::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
{
    if (!includeSelf || !m_width)
        return 0;
    int bottom = m_height;
    if (isRelPositioned())
        bottom += relativePositionOffsetY();
    return bottom;
}

int RenderBox::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
    if (!includeSelf || !m_height)
        return 0;
    int right = m_width;
    if (isRelPositioned())
        right += relativePositionOffsetX();
    return right;
}

int RenderBox::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
    if (!includeSelf || !m_height)
        return m_width;
    int left = 0;
    if (isRelPositioned())
        left += relativePositionOffsetX();
    return left;
}

#undef DEBUG_LAYOUT

⌨️ 快捷键说明

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