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

📄 render_flexbox.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * This file is part of the render object implementation for KHTML. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) *           (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */#include "render_flexbox.h"using namespace DOM;namespace khtml {class FlexBoxIterator {public:    FlexBoxIterator(RenderFlexibleBox* parent) {        box = parent;        if (box->style()->boxOrient() == HORIZONTAL && box->style()->direction() == RTL)            forward = box->style()->boxDirection() != BNORMAL;        else            forward = box->style()->boxDirection() == BNORMAL;        lastOrdinal = 1;         if (!forward) {            // No choice, since we're going backwards, we have to find out the highest ordinal up front.            RenderObject* child = box->firstChild();            while (child) {                if (child->style()->boxOrdinalGroup() > lastOrdinal)                    lastOrdinal = child->style()->boxOrdinalGroup();                child = child->nextSibling();            }        }                reset();    }    void reset() {        current = 0;        currentOrdinal = forward ? 0 : lastOrdinal+1;    }    RenderObject* first() {        reset();        return next();    }        RenderObject* next() {        do {             if (!current) {                if (forward) {                    currentOrdinal++;                     if (currentOrdinal > lastOrdinal)                        return 0;                    current = box->firstChild();                }                else {                    currentOrdinal--;                    if (currentOrdinal == 0)                        return 0;                    current = box->lastChild();                }            }            else                current = forward ? current->nextSibling() : current->previousSibling();            if (current && current->style()->boxOrdinalGroup() > lastOrdinal)                lastOrdinal = current->style()->boxOrdinalGroup();        } while (!current || current->style()->boxOrdinalGroup() != currentOrdinal ||                 current->style()->visibility() == COLLAPSE);        return current;    }private:    RenderFlexibleBox* box;    RenderObject* current;    bool forward;    unsigned int currentOrdinal;    unsigned int lastOrdinal;};    RenderFlexibleBox::RenderFlexibleBox(DOM::NodeImpl* node):RenderBlock(node){    setChildrenInline(false); // All of our children must be block-level    m_flexingChildren = m_stretchingChildren = false;}RenderFlexibleBox::~RenderFlexibleBox(){}void RenderFlexibleBox::calcHorizontalMinMaxWidth(){    RenderObject *child = firstChild();    while (child) {        // positioned children don't affect the minmaxwidth        if (child->isPositioned() || child->style()->visibility() == COLLAPSE)        {            child = child->nextSibling();            continue;        }        int margin=0;        //  auto margins don't affect minwidth        Length ml = child->style()->marginLeft();        Length mr = child->style()->marginRight();        // Call calcWidth on the child to ensure that our margins are        // up to date.  This method can be called before the child has actually        // calculated its margins (which are computed inside calcWidth).        child->calcWidth();        if (!(ml.type==Variable) && !(mr.type==Variable))        {            if (!(child->style()->width().type==Variable))            {                if (child->style()->direction()==LTR)                    margin = child->marginLeft();                else                    margin = child->marginRight();            }            else                margin = child->marginLeft()+child->marginRight();        }        else if (!(ml.type == Variable))            margin = child->marginLeft();        else if (!(mr.type == Variable))            margin = child->marginRight();        if (margin < 0) margin = 0;        m_minWidth += child->minWidth() + margin;        m_maxWidth += child->maxWidth() + margin;        child = child->nextSibling();    }    }void RenderFlexibleBox::calcVerticalMinMaxWidth(){    RenderObject *child = firstChild();    while(child != 0)    {        // Positioned children and collapsed children don't affect the min/max width        if (child->isPositioned() || child->style()->visibility() == COLLAPSE) {            child = child->nextSibling();            continue;        }        Length ml = child->style()->marginLeft();        Length mr = child->style()->marginRight();        // Call calcWidth on the child to ensure that our margins are        // up to date.  This method can be called before the child has actually        // calculated its margins (which are computed inside calcWidth).        if (ml.type == Percent || mr.type == Percent)            calcWidth();        // A margin basically has three types: fixed, percentage, and auto (variable).        // Auto margins simply become 0 when computing min/max width.        // Fixed margins can be added in as is.        // Percentage margins are computed as a percentage of the width we calculated in        // the calcWidth call above.  In this case we use the actual cached margin values on        // the RenderObject itself.        int margin = 0;        if (ml.type == Fixed)            margin += ml.value;        else if (ml.type == Percent)            margin += child->marginLeft();        if (mr.type == Fixed)            margin += mr.value;        else if (mr.type == Percent)            margin += child->marginRight();        if (margin < 0) margin = 0;                int w = child->minWidth() + margin;        if(m_minWidth < w) m_minWidth = w;                w = child->maxWidth() + margin;        if(m_maxWidth < w) m_maxWidth = w;        child = child->nextSibling();    }    }void RenderFlexibleBox::calcMinMaxWidth(){    KHTMLAssert( !minMaxKnown() );    m_minWidth = 0;    m_maxWidth = 0;    if (hasMultipleLines() || isVertical())        calcVerticalMinMaxWidth();    else        calcHorizontalMinMaxWidth();    if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;    if (style()->width().isFixed() && style()->width().value > 0)        m_minWidth = m_maxWidth = style()->width().value;       if (style()->minWidth().isFixed() && style()->minWidth().value > 0) {        m_maxWidth = kMax(m_maxWidth, style()->minWidth().value);        m_minWidth = kMax(m_minWidth, style()->minWidth().value);    }        if (style()->maxWidth().isFixed() && style()->maxWidth().value != UNDEFINED) {        m_maxWidth = kMin(m_maxWidth, style()->maxWidth().value);        m_minWidth = kMin(m_minWidth, style()->maxWidth().value);    }    int toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();    m_minWidth += toAdd;    m_maxWidth += toAdd;    setMinMaxKnown();}void RenderFlexibleBox::layoutBlock(bool relayoutChildren){    KHTMLAssert(needsLayout());    KHTMLAssert(minMaxKnown());    if (!relayoutChildren && posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) {        // All we have to is lay out our positioned objects.        layoutPositionedObjects(relayoutChildren);        if (hasOverflowClip())            m_layer->updateScrollInfoAfterLayout();        setNeedsLayout(false);        return;    }    QRect oldBounds;    bool checkForRepaint = checkForRepaintDuringLayout();    if (checkForRepaint)        oldBounds = getAbsoluteRepaintRect();        int oldWidth = m_width;    int oldHeight = m_height;        calcWidth();    calcHeight();    m_overflowWidth = m_width;    if (oldWidth != m_width || oldHeight != m_height ||        (parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL &&         parent()->style()->boxAlign() == BSTRETCH))        relayoutChildren = true;    m_height = 0;    m_overflowHeight = 0;    m_flexingChildren = m_stretchingChildren = false;    initMaxMarginValues();    if (scrollsOverflow()) {        // For overflow:scroll blocks, ensure we have both scrollbars in place always.        if (style()->overflow() == OSCROLL) {            m_layer->setHasHorizontalScrollbar(true);            m_layer->setHasVerticalScrollbar(true);        }        // Move the scrollbars aside during layout.  The layer will move them back when it        // does painting or event handling.        m_layer->moveScrollbarsAside();    }    if (isHorizontal())        layoutHorizontalBox(relayoutChildren);    else        layoutVerticalBox(relayoutChildren);        oldHeight = m_height;    calcHeight();    if (oldHeight != m_height) {        relayoutChildren = true;        // If the block got expanded in size, then increase our overflowheight to match.        if (m_overflowHeight > m_height)            m_overflowHeight -= (borderBottom()+paddingBottom());        if (m_overflowHeight < m_height)            m_overflowHeight = m_height;    }    layoutPositionedObjects( relayoutChildren );    //kdDebug() << renderName() << " layout width=" << m_width << " height=" << m_height << endl;    if (!isFloatingOrPositioned() && m_height == 0) {        // We are a block with no border and padding and a computed height        // of 0.  The CSS spec states that zero-height blocks collapse their margins        // together.        // When blocks are self-collapsing, we just use the top margin values and set the        // bottom margin max values to 0.  This way we don't factor in the values        // twice when we collapse with our previous vertically adjacent and        // following vertically adjacent blocks.        if (m_maxBottomPosMargin > m_maxTopPosMargin)            m_maxTopPosMargin = m_maxBottomPosMargin;        if (m_maxBottomNegMargin > m_maxTopNegMargin)            m_maxTopNegMargin = m_maxBottomNegMargin;        m_maxBottomNegMargin = m_maxBottomPosMargin = 0;    }    // Always ensure our overflow width is at least as large as our width.    if (m_overflowWidth < m_width)        m_overflowWidth = m_width;    // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if    // we overflow or not.    if (hasOverflowClip())        m_layer->updateScrollInfoAfterLayout();    // Repaint with our new bounds if they are different from our old bounds.    if (checkForRepaint)        repaintAfterLayoutIfNeeded(oldBounds, oldBounds);        setNeedsLayout(false);}void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren){    int toAdd = borderBottom() + paddingBottom();    int yPos = borderTop() + paddingTop();    int xPos = borderLeft() + paddingLeft();    bool heightSpecified = false;    int oldHeight = 0;        unsigned int highestFlexGroup = 0;    unsigned int lowestFlexGroup = 0;    bool haveFlex = false;    int remainingSpace = 0;    m_overflowHeight = m_height;    // The first walk over our kids is to find out if we have any flexible children.    FlexBoxIterator iterator(this);    RenderObject* child = iterator.next();    while (child) {        // Check to see if this child flexes.        if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {            // We always have to lay out flexible objects again, since the flex distribution            // may have changed, and we need to reallocate space.            child->setOverrideSize(-1);            if (!relayoutChildren)                child->setChildNeedsLayout(true, false);            haveFlex = true;            unsigned int flexGroup = child->style()->boxFlexGroup();

⌨️ 快捷键说明

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