📄 render_flexbox.cpp
字号:
/* * 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 + -