📄 renderflexiblebox.cpp
字号:
m_overflowHeight = max(m_overflowWidth, reflection.right()); } } statePusher.pop(); // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if // we overflow or not. if (hasOverflowClip()) layer()->updateScrollInfoAfterLayout(); // Repaint with our new bounds if they are different from our old bounds. repainter.repaintAfterLayout(); setNeedsLayout(false);}void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren){ int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); 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 = height(); // The first walk over our kids is to find out if we have any flexible children. FlexBoxIterator iterator(this); RenderBox* 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(); if (lowestFlexGroup == 0) lowestFlexGroup = flexGroup; if (flexGroup < lowestFlexGroup) lowestFlexGroup = flexGroup; if (flexGroup > highestFlexGroup) highestFlexGroup = flexGroup; } child = iterator.next(); } // We do 2 passes. The first pass is simply to lay everyone out at // their preferred widths. The second pass handles flexing the children. do { // Reset our height. setHeight(yPos); m_overflowHeight = height(); xPos = borderLeft() + paddingLeft(); // Our first pass is done without flexing. We simply lay the children // out within the box. We have to do a layout first in order to determine // our box's intrinsic height. int maxAscent = 0, maxDescent = 0; child = iterator.first(); while (child) { // make sure we relayout children if we need it. if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))) child->setChildNeedsLayout(true, false); if (child->isPositioned()) { child = iterator.next(); continue; } // Compute the child's vertical margins. child->calcVerticalMargins(); // Now do the layout. child->layoutIfNeeded(); // Update our height and overflow height. if (style()->boxAlign() == BBASELINE) { int ascent = child->firstLineBoxBaseline(); if (ascent == -1) ascent = child->height() + child->marginBottom(); ascent += child->marginTop(); int descent = (child->marginTop() + child->height() + child->marginBottom()) - ascent; // Update our maximum ascent. maxAscent = max(maxAscent, ascent); // Update our maximum descent. maxDescent = max(maxDescent, descent); // Now update our height. setHeight(max(yPos + maxAscent + maxDescent, height())); } else setHeight(max(height(), yPos + child->marginTop() + child->height() + child->marginBottom())); child = iterator.next(); } if (!iterator.first() && hasLineIfEmpty()) setHeight(height() + lineHeight(true, true)); setHeight(height() + toAdd); // Always make sure our overflowheight is at least our height. if (m_overflowHeight < height()) m_overflowHeight = height(); oldHeight = height(); calcHeight(); relayoutChildren = false; if (oldHeight != height()) heightSpecified = true; // Now that our height is actually known, we can place our boxes. m_stretchingChildren = (style()->boxAlign() == BSTRETCH); child = iterator.first(); while (child) { if (child->isPositioned()) { child->containingBlock()->insertPositionedObject(child); if (child->style()->hasStaticX()) { if (style()->direction() == LTR) child->layer()->setStaticX(xPos); else child->layer()->setStaticX(width() - xPos); } if (child->style()->hasStaticY()) child->layer()->setStaticY(yPos); child = iterator.next(); continue; } // We need to see if this child's height has changed, since we make block elements // fill the height of a containing box by default. // Now do a layout. int oldChildHeight = child->height(); child->calcHeight(); if (oldChildHeight != child->height()) child->setChildNeedsLayout(true, false); child->layoutIfNeeded(); // We can place the child now, using our value of box-align. xPos += child->marginLeft(); int childY = yPos; switch (style()->boxAlign()) { case BCENTER: childY += child->marginTop() + max(0, (contentHeight() - (child->height() + child->marginTop() + child->marginBottom()))/2); break; case BBASELINE: { int ascent = child->firstLineBoxBaseline(); if (ascent == -1) ascent = child->height() + child->marginBottom(); ascent += child->marginTop(); childY += child->marginTop() + (maxAscent - ascent); break; } case BEND: childY += contentHeight() - child->marginBottom() - child->height(); break; default: // BSTART childY += child->marginTop(); break; } placeChild(child, xPos, childY); if (child->isRenderBlock()) toRenderBlock(child)->addVisualOverflow(toRenderBlock(child)->floatRect()); m_overflowHeight = max(m_overflowHeight, childY + child->overflowHeight(false)); m_overflowTop = min(m_overflowTop, child->y() + child->overflowTop(false)); xPos += child->width() + child->marginRight(); child = iterator.next(); } remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos; m_stretchingChildren = false; if (m_flexingChildren) haveFlex = false; // We're done. else if (haveFlex) { // We have some flexible objects. See if we need to grow/shrink them at all. if (!remainingSpace) break; // Allocate the remaining space among the flexible objects. If we are trying to // grow, then we go from the lowest flex group to the highest flex group. For shrinking, // we go from the highest flex group to the lowest group. bool expanding = remainingSpace > 0; unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup; unsigned int end = expanding? highestFlexGroup : lowestFlexGroup; for (unsigned int i = start; i <= end && remainingSpace; i++) { // Always start off by assuming the group can get all the remaining space. int groupRemainingSpace = remainingSpace; do { // Flexing consists of multiple passes, since we have to change ratios every time an object hits its max/min-width // For a given pass, we always start off by computing the totalFlex of all objects that can grow/shrink at all, and // computing the allowed growth before an object hits its min/max width (and thus // forces a totalFlex recomputation). int groupRemainingSpaceAtBeginning = groupRemainingSpace; float totalFlex = 0.0f; child = iterator.first(); while (child) { if (allowedChildFlex(child, expanding, i)) totalFlex += child->style()->boxFlex(); child = iterator.next(); } child = iterator.first(); int spaceAvailableThisPass = groupRemainingSpace; while (child) { int allowedFlex = allowedChildFlex(child, expanding, i); if (allowedFlex) { int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex())); spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex); } child = iterator.next(); } // The flex groups may not have any flexible objects this time around. if (!spaceAvailableThisPass || totalFlex == 0.0f) { // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group. groupRemainingSpace = 0; continue; } // Now distribute the space to objects. child = iterator.first(); while (child && spaceAvailableThisPass && totalFlex) { if (allowedChildFlex(child, expanding, i)) { int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex)); if (spaceAdd) { child->setOverrideSize(child->overrideWidth() + spaceAdd); m_flexingChildren = true; relayoutChildren = true; } spaceAvailableThisPass -= spaceAdd; remainingSpace -= spaceAdd; groupRemainingSpace -= spaceAdd; totalFlex -= child->style()->boxFlex(); } child = iterator.next(); } if (groupRemainingSpace == groupRemainingSpaceAtBeginning) { // this is not advancing, avoid getting stuck by distributing the remaining pixels child = iterator.first(); int spaceAdd = groupRemainingSpace > 0 ? 1 : -1; while (child && groupRemainingSpace) { if (allowedChildFlex(child, expanding, i)) { child->setOverrideSize(child->overrideWidth() + spaceAdd); m_flexingChildren = true; relayoutChildren = true; remainingSpace -= spaceAdd; groupRemainingSpace -= spaceAdd; } child = iterator.next(); } } } while (groupRemainingSpace); } // We didn't find any children that could grow. if (haveFlex && !m_flexingChildren) haveFlex = false; } } while (haveFlex); m_flexingChildren = false; if (remainingSpace > 0 && ((style()->direction() == LTR && style()->boxPack() != BSTART) || (style()->direction() == RTL && style()->boxPack() != BEND))) { // Children must be repositioned. int offset = 0; if (style()->boxPack() == BJUSTIFY) { // Determine the total number of children.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -