📄 renderflexiblebox.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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#include "RenderFlexibleBox.h"#include "CharacterNames.h"#include "RenderLayer.h"#include "RenderView.h"#include <wtf/StdLibExtras.h>using namespace std;namespace WebCore {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. RenderBox* child = box->firstChildBox(); while (child) { if (child->style()->boxOrdinalGroup() > lastOrdinal) lastOrdinal = child->style()->boxOrdinalGroup(); child = child->nextSiblingBox(); } } reset(); } void reset() { current = 0; currentOrdinal = forward ? 0 : lastOrdinal+1; } RenderBox* first() { reset(); return next(); } RenderBox* next() { do { if (!current) { if (forward) { currentOrdinal++; if (currentOrdinal > lastOrdinal) return 0; current = box->firstChildBox(); } else { currentOrdinal--; if (currentOrdinal == 0) return 0; current = box->lastChildBox(); } } else current = forward ? current->nextSiblingBox() : current->previousSiblingBox(); 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; RenderBox* current; bool forward; unsigned int currentOrdinal; unsigned int lastOrdinal;}; RenderFlexibleBox::RenderFlexibleBox(Node* node):RenderBlock(node){ setChildrenInline(false); // All of our children must be block-level m_flexingChildren = m_stretchingChildren = false;}RenderFlexibleBox::~RenderFlexibleBox(){}void RenderFlexibleBox::calcHorizontalPrefWidths(){ for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { // positioned children don't affect the minmaxwidth if (child->isPositioned() || child->style()->visibility() == COLLAPSE) continue; // A margin basically has three types: fixed, percentage, and auto (variable). // Auto and percentage margins simply become 0 when computing min/max width. // Fixed margins can be added in as is. Length ml = child->style()->marginLeft(); Length mr = child->style()->marginRight(); int margin = 0, marginLeft = 0, marginRight = 0; if (ml.isFixed()) marginLeft += ml.value(); if (mr.isFixed()) marginRight += mr.value(); margin = marginLeft + marginRight; m_minPrefWidth += child->minPrefWidth() + margin; m_maxPrefWidth += child->maxPrefWidth() + margin; } }void RenderFlexibleBox::calcVerticalPrefWidths(){ for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { // Positioned children and collapsed children don't affect the min/max width if (child->isPositioned() || child->style()->visibility() == COLLAPSE) continue; // A margin basically has three types: fixed, percentage, and auto (variable). // Auto/percentage margins simply become 0 when computing min/max width. // Fixed margins can be added in as is. Length ml = child->style()->marginLeft(); Length mr = child->style()->marginRight(); int margin = 0; if (ml.isFixed()) margin += ml.value(); if (mr.isFixed()) margin += mr.value(); int w = child->minPrefWidth() + margin; m_minPrefWidth = max(w, m_minPrefWidth); w = child->maxPrefWidth() + margin; m_maxPrefWidth = max(w, m_maxPrefWidth); } }void RenderFlexibleBox::calcPrefWidths(){ ASSERT(prefWidthsDirty()); if (style()->width().isFixed() && style()->width().value() > 0) m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value()); else { m_minPrefWidth = m_maxPrefWidth = 0; if (hasMultipleLines() || isVertical()) calcVerticalPrefWidths(); else calcHorizontalPrefWidths(); m_maxPrefWidth = max(m_minPrefWidth, m_maxPrefWidth); } if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) { m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value())); m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value())); } if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) { m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); } int toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight(); m_minPrefWidth += toAdd; m_maxPrefWidth += toAdd; setPrefWidthsDirty(false);}void RenderFlexibleBox::layoutBlock(bool relayoutChildren){ ASSERT(needsLayout()); if (!relayoutChildren && layoutOnlyPositionedObjects()) return; LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasTransform() || hasReflection()); int previousWidth = width(); int previousHeight = height(); calcWidth(); calcHeight(); m_overflowWidth = width(); if (previousWidth != width() || previousHeight != height() || (parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL && parent()->style()->boxAlign() == BSTRETCH)) relayoutChildren = true; setHeight(0); m_overflowHeight = 0; m_flexingChildren = m_stretchingChildren = false; initMaxMarginValues(); // For overflow:scroll blocks, ensure we have both scrollbars in place always. if (scrollsOverflow()) { if (style()->overflowX() == OSCROLL) layer()->setHasHorizontalScrollbar(true); if (style()->overflowY() == OSCROLL) layer()->setHasVerticalScrollbar(true); } if (isHorizontal()) layoutHorizontalBox(relayoutChildren); else layoutVerticalBox(relayoutChildren); int oldHeight = height(); calcHeight(); if (oldHeight != height()) { // If the block got expanded in size, then increase our overflowheight to match. if (m_overflowHeight > height()) m_overflowHeight -= (borderBottom() + paddingBottom() + horizontalScrollbarHeight()); if (m_overflowHeight < height()) m_overflowHeight = height(); } if (previousHeight != height()) relayoutChildren = true; layoutPositionedObjects(relayoutChildren || isRoot()); if (!isFloatingOrPositioned() && 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. int pos = maxTopPosMargin(); int neg = maxTopNegMargin(); if (maxBottomPosMargin() > pos) pos = maxBottomPosMargin(); if (maxBottomNegMargin() > neg) neg = maxBottomNegMargin(); setMaxTopMargins(pos, neg); setMaxBottomMargins(0, 0); } // Always ensure our overflow width is at least as large as our width. if (m_overflowWidth < width()) m_overflowWidth = width(); if (!hasOverflowClip()) { for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) { m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur); m_overflowWidth = max(m_overflowWidth, width() + boxShadow->x + boxShadow->blur); m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur); m_overflowHeight = max(m_overflowHeight, height() + boxShadow->y + boxShadow->blur); } if (hasReflection()) { IntRect reflection(reflectionBox()); m_overflowTop = min(m_overflowTop, reflection.y()); m_overflowHeight = max(m_overflowHeight, reflection.bottom()); m_overflowLeft = min(m_overflowLeft, reflection.x());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -